unicode()가 인코딩이 제공되지 않은 개체에서만 str()을 사용하는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/106630

  •  01-07-2019
  •  | 
  •  

문제

먼저 문자열 변수를 만드는 것으로 시작합니다. 비ASCII UTF-8 인코딩된 데이터:

>>> text = 'á'
>>> text
'\xc3\xa1'
>>> text.decode('utf-8')
u'\xe1'

사용 unicode() 그것에 오류가 발생합니다 ...

>>> unicode(text)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: 
                    ordinal not in range(128)

...하지만 인코딩을 알고 있다면 이를 두 번째 매개변수로 사용할 수 있습니다.

>>> unicode(text, 'utf-8')
u'\xe1'
>>> unicode(text, 'utf-8') == text.decode('utf-8')
True

이제 이 텍스트를 반환하는 클래스가 있다면 __str__() 방법:

>>> class ReturnsEncoded(object):
...     def __str__(self):
...         return text
... 
>>> r = ReturnsEncoded()
>>> str(r)
'\xc3\xa1'

unicode(r) 사용하는 것 같다 str() 그것에 대해 동일한 오류가 발생하기 때문에 unicode(text) 위에:

>>> unicode(r)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: 
                    ordinal not in range(128)

지금까지는 모든 것이 계획대로였습니다!

하지만 누구도 예상하지 못했던 것처럼, unicode(r, 'utf-8') 시도조차 하지 않을 것이다:

>>> unicode(r, 'utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: coercing to Unicode: need string or buffer, ReturnsEncoded found

왜?왜 이렇게 일관성 없는 행동을 하는 걸까요?버그인가요?의도한 걸까?매우 어색합니다.

도움이 되었습니까?

해결책

그 행동은 혼란스러워 보이지만 의도적인 것 같습니다.나는 여기에 유니코드 문서 전체를 재현합니다. Python 내장 함수 문서 (이 글을 쓰는 동안 버전 2.5.2의 경우):

유니코드([객체[, 인코딩 [, 오류]]])

다음 모드 중 하나를 사용하여 객체의 유니코드 문자열 버전을 반환합니다.

인코딩 및/또는 오류가 주어지면 Unicode ()는 인코딩을 위해 코덱을 사용하여 8 비트 스트링 또는 문자 버퍼가 될 수있는 객체를 디코딩합니다.인코딩 매개 변수는 인코딩의 이름을 제공하는 문자열입니다.인코딩을 알 수없는 경우 Lookuperror가 제기됩니다.오류 처리는 오류에 따라 수행됩니다.이것은 입력 인코딩에서 유효하지 않은 문자의 처리를 지정합니다.오류가 '엄격한'(기본값) 인 경우 valueError가 오류로 올라가고 '무시'의 값은 오류를 조용히 무시하고 '교체'의 값은 공식 유니 코드 교체 문자 U+FFFD를 유발합니다. 디코딩 할 수없는 입력 문자를 대체하는 데 사용됩니다.또한 참조하십시오 코덱 기준 치수.

선택적 매개 변수가 주어지지 않으면 Unicode ()는 8 비트 문자열 대신 유니 코드 문자열을 반환한다는 점을 제외하고 str ()의 동작을 모방합니다.보다 정확하게는 객체가 유니 코드 문자열 또는 서브 클래스 인 경우 추가 디코딩을 적용하지 않고도 유니 코드 문자열을 반환합니다.

__unicode __ () 메소드를 제공하는 개체의 경우 유니 코드 문자열을 만들기 위해 인수 없이이 메소드를 호출합니다.다른 모든 객체의 경우 8 비트 문자열 버전 또는 표현이 요청 된 다음 'Strict'모드의 기본 인코딩을 위해 코덱을 사용하여 유니 코드 문자열로 변환됩니다.

버전 2.0의 새로운 기능.버전 2.2에서 변경됨:__unicode__()에 대한 지원이 추가되었습니다.

그러니까 전화할 때 unicode(r, 'utf-8'), 첫 번째 인수로 8비트 문자열이나 문자 버퍼가 필요하므로 __str__() 메소드를 사용하여 이를 디코딩하려고 시도합니다. utf-8 코덱.없이 utf-8, unicode() 함수는 a를 찾습니다. __unicode__() 개체에 대한 메서드를 찾았지만 찾지 못한 경우 __str__() 제안한 대로 기본 코덱을 사용하여 유니코드로 변환하려고 시도하는 방법입니다.

다른 팁

unicode 텍스트의 인코딩을 추측하지 않습니다.개체가 다음과 같이 자체적으로 인쇄할 수 있는 경우 unicode, 정의 __unicode__() 유니코드 문자열을 반환하는 메서드입니다.


그 비밀은 unicode(r) 실제로는 전화 안 해 __str__() 그 자체.대신에, 그것은 다음을 찾고 있습니다. __unicode__() 방법.기본 구현은 __unicode__() 전화할 것이다 __str__() 그런 다음 다음을 사용하여 디코딩을 시도합니다. ascii 문자셋.인코딩을 통과하면, unicode() 첫 번째 객체는 디코딩될 수 있는 객체일 것으로 예상합니다. basestring.


'utf-8'을 전달하지 않으면 ASCII로 디코딩을 시도하기 때문에 동작이 이상합니다.하지만 'utf-8'을 전달하면 다른 오류가 발생합니다.

"utf-8"을 지정하면 첫 번째 매개변수를 디코딩할 문자열과 같은 객체로 처리하기 때문입니다.이것이 없으면 매개변수를 유니코드로 강제 변환되는 객체로 처리합니다.

나는 혼란을 이해하지 못한다.그 물건이 무엇인지 안다면 text 속성은 항상 UTF-8로 인코딩됩니다. 정의만 하면 됩니다. __unicode__() 그러면 모든 것이 잘 작동할 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top