파이썬 문자열에서 3 개의 백 슬래시가 4와 같은 이유는 무엇입니까?


90

'?\\\?'=='?\\\\?'주는지 말해 줄래 True? 그것은 나를 미치게 만들고 합리적인 대답을 찾을 수 없습니다 ...

>>> list('?\\\?')
['?', '\\', '\\', '?']
>>> list('?\\\\?')
['?', '\\', '\\', '?']

8
이 끝나는 그래서 후자는 아무 것도 탈출하지 않는 존재는 그 자체 탈출
Padraic 커닝햄을

1
포함 할 필요가 없습니다 list():>>> '?\\\?' '?\\\\?'
daboross

@PadraicCunningham 그것은 "자신이 탈출하는 것으로 끝나지 않습니다". 그게 무슨 뜻이야?
user253751

재미있게도 그 이유는 둘 다 백 슬래시 두 개와 같기 때문입니다. :-)
RemcoGerlich

@immibis, 정확히 무슨 일이 일어나고 있는지. repr과 str의 차이점을 알고 있습니까? 문자열에 하나의 백 슬래시를 모두 인쇄를 시도하고 명확 될 수도
Padraic 커닝햄

답변:


84

기본적으로 파이썬은 백 슬래시 처리에 약간 관대하기 때문입니다. https://docs.python.org/2.0/ref/strings.html 에서 인용 :

표준 C와 달리 인식되지 않는 모든 이스케이프 시퀀스는 문자열에 변경되지 않은 상태 로 남아 있습니다. 즉, 백 슬래시는 문자열에 남아 있습니다.

(원본의 강조)

따라서 파이썬에서는 세 개의 백 슬래시가 4와 같지 않고, 같은 문자로 백 슬래시를 따를 때 인식 된 이스케이프 시퀀스가 ​​아니기 ?때문에 두 개가 함께 두 문자로 나오는 것 \?입니다.


6
그것은 관대함의 반대입니다. 관대함은 "필요하지 않은 캐릭터를 백 슬래시하면 백 슬래시는 아무 일도하지 않는다" 는 대부분의 다른 사람들의 행동입니다. 다른 규칙 (백 슬래시 영숫자는 특별하게 만들 수 있지만 백 슬래시 구두점은 항상 특별하지 않음)과 함께, 어떤 문자가 특별히 어떤 문자인지 알 필요없이 모든 구두점을 백 슬래시하여 안전하게 문자열을 제거 할 수있는 매우 멋진 속성을 얻을 수 있습니다. interpeted — Python에없는 속성입니다.
hobbs

24
아니요, 관대함의 반대는 인식 할 수없는 백 슬래시 이스케이프를 사용할 때 오류를 발생시키는 것입니다. (거의 모든 컴파일 된 언어가 그렇듯이. 파이썬의 문자열 처리는 기본적으로 "유효하지 않은 백 슬래시 이스케이프를 처리 할 때 폭발하지 않는다는 점을 제외하고는 C와 비슷합니다."라는 점을 기억하십시오.) 또한 어떤 언어에서든 이스케이프가 필요한 문자는 두 개뿐입니다. -구분 기호로 사용하는 모든 항목 및 백 슬래시 자체. 둘 다 기억하기 어렵다는 주장을 이해하지 못합니다.
Daniel Martin

@DanielMartin 구분 기호가 자체 이스케이프 문자로 작동하는 일부 언어가 있습니다 (예 :) 'escape''d'. 거기에 다른 캐릭터를 기억할 필요조차 없습니다!
SztupY

1
아 잠깐, 표준 파스칼도 그 시스템을 사용했다고 생각합니다 -nyx.net/~gthompso/self_pasc.txt
Daniel Martin

1
@DanielMartin SQL도 마찬가지입니다.
Random832

30

조합이 유효한 이스케이프 시퀀스를 나타내는 경우 백 슬래시가 바로 뒤에 오는 문자에 대한 이스케이프 문자로 작동하기 때문입니다. 12 개 정도의 이스케이프 시퀀스가 여기나열됩니다 . 여기에는 개행 문자 \n, 가로 탭 \t, 캐리지 리턴 \r과 같은 명백한 문자 와 유니 코드 문자를 나타내는 \N{...}\N{WAVY DASH}를 들어 사용하는 명명 된 유니 코드 문자와 같은 더 모호한 문자가 포함 \u3030됩니다. 요점은 이스케이프 시퀀스가 ​​알려지지 않은 경우 문자 시퀀스가 ​​그대로 문자열에 남아 있다는 것입니다.

문제의 일부는 Python 인터프리터 출력이 사용자를 오도하는 것일 수도 있습니다. 이는 표시 될 때 백 슬래시가 이스케이프되기 때문입니다. 그러나 이러한 문자열 을 인쇄 하면 추가 백 슬래시가 사라집니다.

>>> '?\\\?'
'?\\\\?'
>>> print('?\\\?')
?\\?
>>> '?\\\?' == '?\\?'    # I don't know why you think this is True???
False
>>> '?\\\?' == r'?\\?'   # but if you use a raw string for '?\\?'
True
>>> '?\\\\?' == '?\\\?'  # this is the same string... see below
True

구체적인 예에서 첫 번째 경우 '?\\\?'첫 번째 \는 두 번째 백 슬래시를 이스케이프하고 단일 백 슬래시를 남기지 만 세 번째 백 슬래시는 \?유효한 이스케이프 시퀀스가 ​​아니기 때문에 백 슬래시로 남아 있습니다 . 따라서 결과 문자열은 ?\\?입니다.

두 번째 경우 '?\\\\?'첫 번째 백 슬래시는 두 번째를 이스케이프하고 세 번째 백 슬래시는 네 번째를 이스케이프하여 문자열이 ?\\?됩니다.

그래서 세 개의 백 슬래시가 네 개와 같은 것입니다.

>>> '?\\\?' == '?\\\\?'
True

3 개의 백 슬래시가있는 문자열을 만들려면 각 백 슬래시를 이스케이프 할 수 있습니다.

>>> '?\\\\\\?'
'?\\\\\\?'
>>> print('?\\\\\\?')
?\\\?

또는 "원시"문자열을 더 이해하기 쉽게 찾을 수 있습니다.

>>> r'?\\\?'
'?\\\\\\?'
>>> print(r'?\\\?')
?\\\?

이것은 문자열 리터럴에 대한 이스케이프 시퀀스 처리를 전환합니다. 자세한 내용은 문자열 리터럴 을 참조하십시오.


당신이 바로이있어 '?\\\?'=='?\\?'준다 False내가 잘못 입력. 그것은 '?\\\?'=='?\\\\?'질문에서 알 수 있듯이 수정했습니다.
kozooh

13

때문에 \x문자열에, 때 x와 같은 특별한 backslashable 문자 중 하나가 아닌 n, r, t, 0, 등, 다음 백 슬래시와의 문자열로 평가 x.

>>> '\?'
'\\?'

7

https://docs.python.org/2/reference/lexical_analysis.html의 문자열 리터럴 아래에있는 Python 어휘 분석 페이지에서

인식 된 모든 이스케이프 시퀀스를 나열하는 테이블이 있습니다.

\\는 === \ 인 이스케이프 시퀀스입니다.

\? 이스케이프 시퀀스가 ​​아니며 === \?

따라서 '\\\\'는 '\\'이고 뒤에 '\\'는 '\\'(둘은 이스케이프 된 \)입니다.

그리고 '\\\'는 '\\'다음에 '\'이 나옵니다. 또한 '\\'(하나는 이스케이프 \ 및 하나는 원시 \)입니다.

또한 파이썬은 다른 언어와 달리 문자열 리터럴을 둘러싼 작은 따옴표와 큰 따옴표를 구별하지 않습니다.

따라서 '문자열'과 "문자열"은 파이썬에서 정확히 동일하며 이스케이프 시퀀스의 해석에 영향을주지 않습니다.


1

mhawke의 답변은 거의 그것을 다루고 있습니다.이 동작을 설명하는 최소한의 예와 함께 더 간결한 형식으로 다시 설명하고 싶습니다.

추가해야 할 한 가지는 이스케이프 처리가 왼쪽에서 오른쪽으로 이동하므로 \n먼저 백 슬래시를 찾은 다음 이스케이프 할 문자를 찾은 다음이를 찾아서 n이스케이프한다는 것입니다. \\n첫 번째 백 슬래시를 찾고 두 번째 백 슬래시를 찾아 이스케이프 한 다음 n리터럴 n으로 찾아서 봅니다. \?백 슬래시를 찾아 이스케이프 할 문자를 찾고, 이스케이프 ?할 수없는 문자를 찾아 \문자 그대로 백 슬래시로 처리합니다 .

mhawke가 언급했듯이 여기서 핵심은 대화 형 인터프리터가 문자열을 표시 할 때 백 슬래시를 이스케이프한다는 것입니다. 그 이유는 인터프리터에서 코드 편집기로 복사 한 텍스트 문자열이 유효한 파이썬 문자열인지 확인하는 것입니다. 그러나이 경우 편의상이 허용은 혼란을 야기합니다.

>>> print('\?') # \? is not a valid escape code so backslash is left as-is
\?
>>> print('\\?') # \\ is a valid escape code, resulting in a single backslash
'\?'

>>> '\?' # same as first example except that interactive interpreter escapes the backslash
\\?
>>> '\\?' # same as second example, backslash is again escaped
\\?
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.