“u”및“r”문자열 플래그는 정확히 무엇을하며 원시 문자열 리터럴은 무엇입니까?


652

묻는 동안 이 질문을 나는 원시 문자열에 대해 많이 모른다는 것을 깨달았습니다. 장고 트레이너라고 주장하는 누군가에게 이것은 짜증납니다.

인코딩이 무엇인지 알고 있습니다. u'' 있으며 유니 코드가 무엇인지 혼자 있습니다.

  • 그러나 무엇을 하는가 r'' 정확히 무엇을합니까? 어떤 종류의 문자열이 발생합니까?

  • 그리고 무엇보다 도대체 무엇을 ur'' 하는가?

  • 마지막으로 유니 코드 문자열에서 간단한 원시 문자열로 되돌릴 수있는 신뢰할 수있는 방법이 있습니까?

  • 아, 그런데 시스템과 텍스트 편집기 문자셋이 UTF-8로 설정되어 u''있다면 실제로 어떤 작업을 수행합니까?

답변:


683

실제로 "원시 문자열 "은 없습니다. 원시 문자열 리터럴 이 있는데, 이는 'r'여는 따옴표 앞에 정확하게 표시된 문자열 리터럴 입니다.

"원시 문자열 리터럴"은 문자열 리터럴에 대해 약간 다른 구문으로, \백 슬래시는 "백 슬래시 만"을 의미하는 것으로 간주됩니다 (그렇지 않으면 리터럴을 종료하는 인용 부호 바로 앞에 오는 경우 제외). 줄 바꿈, 탭, 백 스페이스, 용지 넘김 등을 나타내는 "이스케이프 시퀀스" 일반적인 문자열 리터럴에서는 이스케이프 시퀀스의 시작으로 간주되지 않도록 각 백 슬래시를 두 배로 늘려야합니다.

이 구문 변형은 주로 정규 표현식 패턴의 구문이 백 슬래시로 무겁기 때문에 존재하지만 (결국 끝이 아니므로 위의 "except"절은 중요하지 않음) 각 패턴을 두 배로 늘리지 않으면 약간 더 좋아 보입니다. - 그게 다야. 또한 기본 Windows 파일 경로 (다른 플랫폼에서와 같이 일반 슬래시 대신 백 슬래시 포함)를 표현하는 데 어느 정도 인기를 얻었지만, 거의 필요하지 않습니다 (일반 슬래시는 Windows에서도 잘 작동하기 때문에). 위).

r'...'(파이썬 2 *)에서 바이트 스트링이다 ur'...'유니 코드 문자열 (역시, 파이썬 2 *)가 있으며, 인용 세 종류의 기타 임의의 문자열도 정확히 동일한 유형을 생성은 (따라서, 예를 들면 r'...', r'''...''', r"...", r"""..."""모든 바이트 문자열 등).

"돌아 가기 " 가 무슨 뜻인지 잘 모르겠습니다. 원시 문자열 유형 이 없기 때문에 본질적으로 앞뒤로 방향이 없습니다. 이는 정상적인 문자열 객체, 바이트 또는 유니 코드를 그대로 표현하는 대체 구문 일뿐입니다.

그리고 네, 파이썬 2. *에, u'...' 이다 단지 구별 물론 항상의 '...'- 전자는 유니 코드 문자열, 후자는 바이트 문자열입니다. 리터럴을 표현하는 것은 완전히 직교하는 문제입니다.

예를 들어 (Python 2.6)을 고려하십시오.

>>> sys.getsizeof('ciao')
28
>>> sys.getsizeof(u'ciao')
34

물론 유니 코드 객체는 더 많은 메모리 공간을 필요로합니다.


6
"r"을 이해한다고해서 어떤 유형이나 인코딩 문제도 의미하지는 않으며 훨씬 간단합니다.
전자 Satis

23
\ u는 ru 모드의 유니 코드 이스케이프 시퀀스이므로 ru "C : \ foo \ unstable"은 실패합니다. r 모드에는 \ u가 없습니다.
커티스 얄롭

26
참고 것을 ur교환 법칙이 성립하지 않습니다는 : ur'str'작품 ru'str'나던. (적어도 win7의 ipython 2.7.2에서)
RafiK

7
방금 r문자열을 테스트 \ 하고 마지막 문자 인 경우 리터럴로 사용되지 않고 대신 닫는 따옴표를 이스케이프하여을 발생시키는 것으로 나타났습니다 SyntaxError: EOL while scanning string literal. 따라서 백 슬래시로 끝나는 문자열 \\ 의 최종 인스턴스에 여전히 사용해야합니다 \ .
Enteleform

1
python sys.getsizeof('cioa') == sys.getsizeof(r'cioa') == sys.getsizeof(u'cioa')3.x-(UTF8 lang을 사용하는 우분투 16.04). 마찬가지로 type('cioa') == type(r'cioa') == type(u'cioa'). 그러나 원시 문자열 보간은 차이를 만듭니다.sys.getsizeof('\ncioa') == sys.getsizeof(u'\ncioa') != sys.getsizeof(r'\ncioa')
Darren Weber

177

파이썬에는 전통적인 str유형과 최신 유형의 두 가지 유형의 문자열이 있습니다 unicode. u앞에 문자가없는 문자열 리터럴을 입력하면 str8 비트 문자를 저장 하는 이전 유형이 표시 u되고 앞에는 최신 문자가 표시 됩니다unicode 유니 코드 문자를 저장할 유형이 표시됩니다.

r그냥 문자열의 문자를 해석하는 방식을 변경, 전혀 유형을 변경하지 않습니다. 이 없으면 r백 슬래시는 이스케이프 문자로 처리됩니다. 로 r백 슬래시는 리터럴로 취급됩니다. 어느 쪽이든, 유형은 동일합니다.

ur 물론 백 슬래시는 이스케이프 코드의 일부가 아닌 리터럴 백 슬래시 인 유니 코드 문자열입니다.

str()함수를 사용하여 유니 코드 문자열을 이전 문자열로 변환하려고 시도 할 수 있지만 이전 문자열에 표시 할 수없는 유니 코드 문자가 있으면 예외가 발생합니다. 원하는 경우 먼저 물음표로 대체 할 수 있지만 물론 이러한 문자는 읽을 수 없습니다. str유니 코드 문자를 올바르게 처리 하려면 유형 을 사용하지 않는 것이 좋습니다 .


고마워요 내가 말했듯이, 나는 유니 코드가 무엇인지 알지 못하고 "r"이 무엇인지, "u"와 "r"의 조합이 무엇인지 몰랐습니다. 나는 더 잘 알고, 건배.
전자 Satis

6
백 슬래시는 원시 문자열 리터럴에서 리터럴로 처리되지 않으므로 r"\"구문 오류가 발생합니다.

4
Python 2에만 적용됩니다.
PaulMcG

60

'원시 문자열' 은 표시되는대로 저장됨을 의미합니다. 예를 들어, '\'단지 인 백 슬래시 대신의 이스케이프 .


3
... 문자열의 마지막 문자가 아닌 한, 닫는 따옴표를 이스케이프하지 않습니다.
jez

36

"u"접두사는 값이 unicode아닌 유형을 나타냅니다.str .

"r"접두어가있는 원시 문자열 리터럴은 그 안에 이스케이프 시퀀스를 이스케이프하므로 len(r"\n")2도 이스케이프합니다. 이스케이프 시퀀스를 이스케이프하기 때문에 단일 이스케이프로 문자열 리터럴을 끝낼 수 없습니다. 유효한 이스케이프 시퀀스가 ​​아닙니다 (예 :r"\" .

"Raw"는 유형의 일부가 아니며 값을 나타내는 한 가지 방법 일뿐입니다. 예를 들어, "\\n"r"\n"마찬가지로 동일한 값이며 32, 0x20그리고 0b100000동일하다.

유니 코드 원시 문자열 리터럴을 가질 수 있습니다.

>>> u = ur"\n"
>>> print type(u), len(u)
<type 'unicode'> 2

소스 파일 인코딩은 소스 파일을 해석하는 방법 만 결정하며 표현식이나 유형에는 영향을 미치지 않습니다. 그러나 ASCII 이외의 인코딩으로 의미가 변경되는 코드는 사용하지 않는 것이 좋습니다 .

ASCII (또는 Python 3.0의 경우 UTF-8)를 사용하는 파일에는 코딩 쿠키가 없어야합니다. Latin-1 (또는 UTF-8)은 주석 또는 문서 문자열에 Latin-1이 필요한 작성자 이름을 언급해야하는 경우에만 사용해야합니다. 그렇지 않으면 \ x, \ u 또는 \ U 이스케이프를 사용하는 것이 ASCII가 아닌 데이터를 문자열 리터럴에 포함시키는 데 선호되는 방법입니다.


30

간단히 설명하겠습니다 : 파이썬 2에서는 문자열을 2 가지 유형으로 저장할 수 있습니다.

첫 번째는 파이썬에서 str 유형 인 ASCII 이며 1 바이트의 메모리를 사용합니다. (256 자, 주로 영어 알파벳과 간단한 기호를 저장합니다)

두 번째 유형은 유니 코드유니 코드입니다 파이썬의 유형 인 . 유니 코드는 모든 유형의 언어를 저장합니다.

기본적으로 파이썬은 str 유형 을 선호 하지만 유니 코드 유형으로 문자열을 저장 하려면 u'text ' 와 같은 텍스트 앞에 u넣거나 호출 하여이 작업을 수행 할 수 있습니다 unicode ('text ')를

따라서 ustr유니 코드 로 캐스팅하는 함수를 호출하는 짧은 방법 입니다. 그게 다야!

이제 r 부분은 텍스트 앞에 텍스트를 넣어 텍스트가 원시 텍스트임을 나타내며 백 슬래시는 이스케이프 문자가 아니어야합니다. r '\ n' 은 줄 바꾸기 문자를 만들지 않습니다. 단지 2 개의 문자를 포함하는 일반 텍스트입니다.

당신은 변환 할 경우 는 str유니 코드 와도 원시 텍스트를 사용 넣어 통해 UR 때문에를 RU 가 오류를 발생 .

이제 중요한 부분 :

r 을 사용하여 하나의 백 슬래시를 저장할 수 없습니다 . 유일한 예외입니다. 따라서이 코드는 오류를 생성합니다 : r '\'

백 슬래시 (하나만)를 저장하려면 '\\' 를 사용해야합니다.

하나 이상의 문자를 저장하려면 r 과 같은 r '\\' 을 계속 사용할 수 있습니다 . 예상 한대로 2 개의 백 슬래시가 생성됩니다.

내가 왜 이유를 모르는 r은 하나 개의 백 슬래시 저장 작동하지 않습니다하지만 이유가 아직 누군가에 의해 설명되지 않는다. 나는 그것이 버그이기를 바랍니다.


9
당신 r'\'은 불법 일뿐만 아니라 '\'어떤 끈의 꼬리에도 싱글 을 넣을 수 없습니다 . r'xxxxxx\'불법 문자열 처럼 .
diverger

파이썬 3은 어떻습니까?
Krissh September

1
@Krissh 모든 파이썬 3 문자열은 유니 코드를 지원합니다. 유형은입니다 str. 더 나은 이해를 위해 여기를 읽으십시오 : medium.com/better-programming/…
off99555

4

어쩌면 이것은 분명하지는 않지만 x = chr (92)를 호출 하여 문자열 '\' 을 만들 수 있습니다.

x=chr(92)
print type(x), len(x) # <type 'str'> 1
y='\\'
print type(y), len(y) # <type 'str'> 1
x==y   # True
x is y # False

4
x is ypython3에서 True로 평가됩니까?
Habeeb Perwad

5
@HabeebPerwad, 즉 문자열 interning 때문입니다 . 인턴 x is y으로 True인해 평가 되는 사실에 의존해서는 안됩니다 . 대신 사용하십시오 x == y(x와 y가 단일 메모리 위치에 저장된 동일한 객체인지 여부를 확인하지 않는 경우).
Lucubrator 2009

4

유니 코드 문자열 리터럴

유니 코드 문자열 리터럴 (접두사가 붙은 문자열 리터럴 u)은 더 이상 Python 3에서 사용되지 않습니다. 여전히 유효하지만 호환성을 위해서만 사용됩니다. Python 2 됩니다.

원시 문자열 리터럴

영어 문자 나 숫자와 같이 쉽게 입력 할 수있는 문자로만 구성된 문자열 리터럴을 만들려면 간단히 입력하면 'hello world'됩니다. 그러나 좀 더 이국적인 캐릭터도 포함 시키려면 해결 방법을 사용해야합니다. 해결 방법 중 하나는 이스케이프 시퀀스 입니다. 이런 식으로 예를 들어 \n문자열 리터럴에 쉽게 입력 할 수있는 두 문자 를 추가하여 문자열에서 새 줄을 나타낼 수 있습니다 . 따라서 'hello\nworld'문자열 을 인쇄하면 단어가 별도의 줄에 인쇄됩니다. 매우 편리합니다!

반면에 이스케이프 시퀀스를 포함하는 문자열 리터럴을 만들려고하지만 파이썬에서 해석하지 않으려는 상황이 있습니다. 당신은 그들이 날 것이기 를 원합니다 . 다음 예를보십시오.

'New updates are ready in c:\windows\updates\new'
'In this lesson we will learn what the \n escape sequence does.'

이러한 상황에서 문자열 리터럴 앞에 r다음 r'hello\nworld'과 같은 문자 를 붙일 수 있습니다. 이스케이프 시퀀스는 Python에서 해석되지 않습니다. 문자열은 생성 한 그대로 인쇄됩니다.

원시 문자열 리터럴이 완전히 "원시"되지 않습니까?

많은 사람들은 원시 문자열 리터럴이 "따옴표 사이에있는 것은 파이썬에 의해 무시된다" . 사실이 아닙니다. 파이썬은 여전히 ​​모든 이스케이프 시퀀스를 인식하지만 해석하지는 않습니다. 대신 변경되지 않습니다. 는 것을 의미한다 원시 문자열 리터럴은 여전히 유효한 문자열 리터럴해야 .

로부터 어휘 정의문자열 리터럴 에서 :

string     ::=  "'" stringitem* "'"
stringitem ::=  stringchar | escapeseq
stringchar ::=  <any source character except "\" or newline or the quote>
escapeseq  ::=  "\" <any source character>

작은 따옴표 문자를 포함 'hello'world'하거나 백 슬래시 : 'hello world\'로 끝나는 문자열 리터럴 (원시 또는 미사용) 은 유효하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.