[python] Python str 대 유니 코드 유형

파이썬 2.7 작업, 나는 진짜 장점은 형식을 사용하여이 무엇인지 궁금하네요 unicode대신 str둘 다 유니 코드 문자열을 보유 할 수있을 것 같은. unicode이스케이프 문자를 사용하여 문자열에 유니 코드 코드를 설정할 수 있다는 것 외에 특별한 이유가 \있습니까? :

다음을 사용하여 모듈 실행 :

# -*- coding: utf-8 -*-

a = 'á'
ua = u'á'
print a, ua

결과 : á, á

편집하다:

Python 셸을 사용한 추가 테스트 :

>>> a = 'á'
>>> a
'\xc3\xa1'
>>> ua = u'á'
>>> ua
u'\xe1'
>>> ua.encode('utf8')
'\xc3\xa1'
>>> ua.encode('latin1')
'\xe1'
>>> ua
u'\xe1'

따라서 unicode문자열은 latin1대신 사용하여 인코딩되는 것처럼 보이고 utf-8원시 문자열은 utf-8? 나는 지금 더 혼란스러워! :에스



답변

unicode텍스트 를 처리하기위한 입니다. 텍스트는 단일 바이트보다 클 수 있는 일련의 코드 포인트 입니다 . 텍스트 수 부호화 원시 바이트로 텍스트를 나타 내기 위해 특정 인코딩 (예 , …).utf-8latin-1

참고 unicode 인코딩되지 않은 ! 파이썬에서 사용하는 내부 표현은 구현 세부 사항이며 원하는 코드 포인트를 표현할 수있는 한 신경 쓰지 않아야합니다.

반대로 strPython 2에서는 일반 바이트 시퀀스입니다 . 텍스트를 나타내지 않습니다!

unicode를 통해 표현되는 이진 데이터 시퀀스로 다양한 방식으로 인코딩 될 수있는 일부 텍스트의 일반적인 표현으로 생각할 수 있습니다 str.

참고 : Python 3에서는 unicode로 이름이 바뀌 었으며 일반 바이트 시퀀스에 대한 str새로운 bytes유형이 있습니다.

확인할 수있는 몇 가지 차이점은 다음과 같습니다.

>>> len(u'à')  # a single code point
1
>>> len('à')   # by default utf-8 -> takes two bytes
2
>>> len(u'à'.encode('utf-8'))
2
>>> len(u'à'.encode('latin1'))  # in latin1 it takes one byte
1
>>> print u'à'.encode('utf-8')  # terminal encoding is utf-8
à
>>> print u'à'.encode('latin1') # it cannot understand the latin1 byte

를 사용 str하면 특정 인코딩 표현의 단일 바이트에 대한 하위 수준 제어가있는 반면를 사용 unicode하면 코드 포인트 수준에서만 제어 할 수 있습니다. 예를 들어 다음을 수행 할 수 있습니다.

>>> 'àèìòù'
'\xc3\xa0\xc3\xa8\xc3\xac\xc3\xb2\xc3\xb9'
>>> print 'àèìòù'.replace('\xa8', '')
à�ìòù

이전에 유효한 UTF-8은 더 이상 아닙니다. 유니 코드 문자열을 사용하면 결과 문자열이 유효한 유니 코드 텍스트가 아닌 방식으로 작동 할 수 없습니다. 코드 포인트를 제거하고 코드 포인트를 다른 코드 포인트로 대체 할 수는 있지만 내부 표현을 망칠 수는 없습니다.


답변

유니 코드와 인코딩은 완전히 다르며 관련이 없습니다.

유니 코드

각 문자에 숫자 ID를 할당합니다.

  • 0x41 → A
  • 0xE1 → á
  • 0x414 → Д

따라서 유니 코드는 A에 0x41, á에 0xE1, Д에 0x414를 할당합니다.

내가 사용한 작은 화살표조차도 유니 코드 번호가 0x2192입니다. 그리고 이모티콘에도 유니 코드 번호가 있습니다. ?는 0x1F602입니다.

이 표 에있는 모든 문자의 유니 코드 번호를 조회 할 수 있습니다 . 특히 위의 처음 세 글자 , 여기 에 화살표, 여기 에 그림 이모티콘을 찾을 수 있습니다 .

유니 코드로 모든 문자에 할당 된 이러한 숫자를 코드 포인트 라고 합니다 .

이 모든 것의 목적은 각 문자를 명확하게 참조하는 수단을 제공하는 것입니다. 예를 들어, 내가 ?에 대해 이야기하고 있다면, “당신도 알다시피 눈물을 흘리는이 웃음 이모티콘” 이라고 말하는 대신 유니 코드 코드 포인트 0x1F602 라고 말할 수 있습니다 . 더 쉬웠 죠?

유니 코드 코드 포인트는 일반적으로 선행으로 형식이 지정되고 U+16 진수 값은 4 자리 이상으로 채워집니다. 따라서 위의 예는 U + 0041, U + 00E1, U + 0414, U + 2192, U + 1F602입니다.

유니 코드 코드 포인트의 범위는 U + 0000에서 U + 10FFFF입니다. 그것은 1,114,112 개의 숫자입니다. 이 숫자 중 2048 개가 서로 게이트 에 사용되므로 1,112,064 개가 남아 있습니다. 즉, 유니 코드는 1,112,064 개의 고유 문자에 고유 ID (코드 포인트)를 할당 할 수 있습니다. 이 모든 코드 포인트가 아직 문자에 할당 된 것은 아니며 유니 코드는 지속적으로 확장됩니다 (예 : 새 이모 지 도입시).

기억해야 할 중요한 점은 유니 코드가 수행하는 모든 작업은 쉽고 명확한 참조를 위해 각 문자에 코드 포인트라는 숫자 ID를 할당하는 것입니다.

인코딩

문자를 비트 패턴에 매핑합니다.

이러한 비트 패턴은 컴퓨터 메모리 또는 디스크의 문자를 나타내는 데 사용됩니다.

다양한 문자 하위 집합을 다루는 다양한 인코딩이 있습니다. 영어권 세계에서 가장 일반적인 인코딩은 다음과 같습니다.

ASCII

지도 128 자 길이 7의 비트 패턴에 (U + 007F에 코드 포인트 U + 0000).

예:

  • a → 1100001 (0x61)

테이블 에서 모든 매핑을 볼 수 있습니다 .

ISO 8859-1 (일명 Latin-1)

매핑 191 자 길이 8 비트 패턴에 (U + 0020 U + 00FF에 U + 007E 및 U + 00A0에 코드 포인트).

예:

  • a → 01100001 (0x61)
  • á → 11100001 (0xE1)

테이블 에서 모든 매핑을 볼 수 있습니다 .

UTF-8

지도 1,112,064 자 중 길이가 8, 16, 24, 또는 32 비트의 비트 패턴들 (기존의 유니 코드 코드 포인트) (즉, 1, 2, 3 또는 4 바이트).

예:

  • a → 01100001 (0x61)
  • á → 11000011 10100001 (0xC3 0xA1)
  • ≠ → 11100010 10001001 10100000 (0xE2 0x89 0xA0)
  • ? → 11110000 10011111 10011000 10000010 (0xF0 0x9F 0x98 0x82)

UTF-8이 문자를 비트 문자열로 인코딩하는 방법은 여기에 잘 설명되어 있습니다 .

유니 코드 및 인코딩

위의 예를 살펴보면 유니 코드가 얼마나 유용한 지 분명해집니다.

예를 들어 내가 Latin-1 이고 á의 인코딩을 설명하고 싶다면 다음과 같이 말할 필요가 없습니다.

“나는 aigu를 사용하여 (또는 상승 막대라고 부르는)이를 11100001로 인코딩합니다.”

하지만 다음과 같이 말할 수 있습니다.

“U + 00E1을 11100001로 인코딩합니다.”

그리고 내가 UTF-8 이라면 다음과 같이 말할 수 있습니다.

“저는 차례로 U + 00E1을 11000011 10100001로 인코딩합니다.”

그리고 우리가 의미하는 캐릭터는 모두에게 분명합니다.

이제 종종 발생하는 혼란에

이진수로 해석하면 인코딩의 비트 패턴이이 문자의 유니 코드 코드 포인트와 같을 때도 있습니다.

예를 들면 :

  • 아스키 인코딩 은 16 진수로 해석 할 수 1,100,001, 등 이 0x61 , 그리고 유니 코드 코드 포인트 a는 이다 U + 0061 .
  • Latin-1은 á 를 11100001로 인코딩 하며, 16 진수 0xE1 로 해석 할 수 있으며 á 의 유니 코드 코드 포인트 는 U + 00E1 입니다.

물론 이것은 편의상 의도적으로 이렇게 배열되었습니다. 그러나 당신은 그것을 순수한 우연의 일치 로보아야합니다 . 메모리에서 문자를 나타내는 데 사용되는 비트 패턴은이 문자의 유니 코드 코드 포인트에 어떤 식 으로든 연결되어 있지 않습니다.

아무도 11100001과 같은 비트 문자열을 이진수로 해석해야한다고 말하지도 않습니다. Latin-1이 문자 á 를 인코딩하는 데 사용하는 비트 시퀀스로보십시오 .

질문으로 돌아 가기

Python 인터프리터에서 사용하는 인코딩은 UTF-8 입니다.

귀하의 예에서 진행되는 작업은 다음과 같습니다.

예 1

다음은 문자 á를 UTF-8로 인코딩합니다. 그 결과 변수에 저장된 11000011 10100001 비트 문자열이 생성됩니다 a.

>>> a = 'á'

의 값을 볼 때 a내용 11000011 10100001은 16 진수 0xC3 0xA1로 형식이 지정되고 다음과 같이 출력됩니다 '\xc3\xa1'.

>>> a
'\xc3\xa1'

예 2

다음은 U + 00E1 인 á의 유니 코드 코드 포인트를 변수에 ua저장합니다 (Python이 내부적으로 메모리에서 코드 포인트 U + 00E1을 표현하기 위해 어떤 데이터 형식을 사용하는지 알지 못하며 중요하지 않습니다).

>>> ua = u'á'

의 값을 볼 때 uaPython은 코드 포인트 U + 00E1이 포함되어 있음을 알려줍니다.

>>> ua
u'\xe1'

예제 3

다음은 UTF-8로 유니 코드 코드 포인트 U + 00E1 (문자 á를 나타냄)을 인코딩하여 결과적으로 비트 패턴 11000011 10100001이됩니다. 다시 출력을 위해이 비트 패턴은 16 진수 0xC3 0xA1로 표시됩니다.

>>> ua.encode('utf-8')
'\xc3\xa1'

예 4

다음은 유니 코드 코드 포인트 U + 00E1 (문자 á를 나타냄)을 Latin-1로 인코딩하여 결과적으로 비트 패턴 11100001이됩니다. 출력의 경우이 비트 패턴은 16 진수 0xE1로 표시되며 이는 우연히 초기 값과 동일합니다. 코드 포인트 U + 00E1 :

>>> ua.encode('latin1')
'\xe1'

유니 코드 개체 ua와 Latin-1 인코딩 사이에는 관계가 없습니다 . á의 코드 포인트는 U + 00E1이고 á의 Latin-1 인코딩은 0xE1 (인코딩의 비트 패턴을 이진수로 해석하는 경우)이라는 것은 순수한 우연입니다.


답변

터미널이 UTF-8로 구성됩니다.

인쇄가 a작동 한다는 사실 은 우연입니다. 원시 UTF-8 바이트를 터미널에 쓰고 있습니다. a는 2 바이트, 16 진 값 C3 및 A1을 포함하는 길이 2 의 값이고 ,은 코드 포인트 U + 00E1을 포함하는 ua길이 1 의 유니 코드 값입니다 .

이러한 길이 차이는 유니 코드 값을 사용하는 주요 이유 중 하나입니다. 바이트 문자열 의 텍스트 문자 수를 쉽게 측정 할 수 없습니다 . len()바이트 문자열의 많은 문자 인코딩이 아닙니까 얼마나 많은 바이트가 사용 된 방법을 알려줍니다.

유니 코드 값을 다른 출력 인코딩으로 인코딩 하면 차이를 확인할 수 있습니다 .

>>> a = 'á'
>>> ua = u'á'
>>> ua.encode('utf8')
'\xc3\xa1'
>>> ua.encode('latin1')
'\xe1'
>>> a
'\xc3\xa1'

유니 코드 표준의 처음 256 개 코드 포인트는 Latin 1 표준과 일치하므로 U + 00E1 코드 포인트는 16 진수 값 E1을 가진 바이트로 Latin 1로 인코딩됩니다.

또한 Python은 유니 코드 및 바이트 문자열 표현에 이스케이프 코드를 사용하고 인쇄 할 수없는 ASCII 코드 포인트도 \x..이스케이프 값을 사용하여 표현 합니다. 이런 이유로 128 255 외모 사이의 코드 포인트 유니 코드 문자열 단지 라틴어 1 인코딩있다. U + 00FF를 초과하는 코드 포인트가있는 유니 코드 문자열이있는 경우 \u....4 자리 16 진수 값과 함께 다른 이스케이프 시퀀스 가 대신 사용됩니다.

유니 코드와 인코딩의 차이점이 무엇인지 아직 완전히 이해하지 못한 것 같습니다. 계속하기 전에 다음 기사를 읽으십시오.


답변

a를 유니 코드로 정의하면 문자 a와 á가 동일합니다. 그렇지 않으면 á는 두 문자로 계산됩니다. len (a) 및 len (au)를 시도하십시오. 그 외에도 다른 환경에서 작업 할 때 인코딩이 필요할 수 있습니다. 예를 들어 md5를 사용하면 a와 ua에 대해 다른 값을 얻습니다.


답변