2008-09-20 4 views
5

나는 그것에 몇 가지 비 ASCIIUTF-8 인코딩 된 데이터와 문자열 변수를 작성하여 시작합니다왜 unicode()는 인코딩이없는 객체 만 str()을 사용합니까?

>>> 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) 

사용. 그러나 인코딩을 알면 두 번째 매개 변수로 사용할 수 있습니다.

나는 __str__() 방법이 텍스트 반환하는 클래스가 이제 경우 : 지금까지

>>> 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(text)과 같은 오류가 발생하기 때문에,

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

unicode(r) 그것에 str()를 사용하는 것을 모든 것이 계획대로!

그러나 이제까지 기대 아무도 같은

, 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 

이유는 무엇입니까? 왜이 모순 된 행동? 그게 버그 야? 의도 된거야? 매우 어색함.

답변

7

동작은 혼란 스럽지만 의도적 인 것처럼 보입니다. 나는 여기서 유니 코드 문서의 전체를 Python Built-In Functions documentation (버전 2.5)에서 재현했다.2, I)이 물품 같이

유니 코드 ([오브젝트 [인코딩 [오류]])

복귀 다음 모드 중 하나를 사용하여 오브젝트의 유니 코드 문자열 버전 :

을 인코딩 및/또는 에러가 주어지면

는 유니 코드()는 8 비트의 문자열 또는 부호화 코덱을 이용하여 문자 버퍼 될 수 어느 오브젝트를 디코딩한다. 인코딩 매개 변수는 인코딩 이름을 제공하는 문자열 입니다. 인코딩을 알 수없는 경우 LookupError가 발생합니다. 오류 처리는 오류에 따라 수행됩니다. 이것은 입력 인코딩에서 인 문자의 처리를 지정합니다. 오류가 'strict'(기본값 : ) 인 경우 오류가 발생하면 ValueError가 발생하고 의 값으로 'ignore'를 지정하면 오류가 자동으로 무시되고 'replace'값으로 인해 공식 유니 코드 대체 문자 이 발생합니다 U + FFFD, 을 디코딩 할 수없는 입력 문자를 대체하는 데 사용됩니다. codecs 모듈을 참조하십시오. 더 선택적 매개 변수를 제공하지 않으면

는 유니 코드는()()는 유니 코드 문자열 대신 8 비트 문자열을 반환하는 것을 제외하고 STR의 동작을 모방합니다. 보다 정확하게는 object가 유니 코드 문자열 또는 하위 클래스 인 경우 추가 디코딩을 적용하지 않고 해당 유니 코드 문자열을 반환합니다.

__unicode __() 메서드를 제공하는 객체의 경우 유니 코드 문자열을 만들기 위해 인수없이 메서드를 호출합니다. 다른 모든 객체에 대해 8 비트의 문자열 버전 또는 표현 요청하고 "엄격한"모드에서 기본 인코딩 코덱 를 이용한 유니 코드 문자열로 변환된다.

버전 2.0의 새로운 기능. 버전 2.2에서 변경됨 : __unicode __() 지원이 추가되었습니다. 당신이 unicode(r, 'utf-8')를 호출 할 때

그래서, 그것은 8 비트 문자열이나 첫 번째 인수로 문자 버퍼가 필요합니다, 그래서 그것은 __str__() 방법을 사용하여 개체를 강제 변환하고, utf-8 코덱을 사용하는 것을 디코딩을 시도합니다. utf-8없이, unicode() 기능은 개체에 __unicode__() 방법에 대한 찾습니다, 당신이 제안을 찾지 못하는 경우, 유니 코드로 변환 할 기본 코덱을 사용하는 시도는 __str__() 메소드를 호출합니다.

4

unicode은 텍스트 인코딩을 추측하지 않습니다. 개체가 자체로 unicode으로 인쇄 할 수있는 경우 유니 코드 문자열을 반환하는 __unicode__() 메서드를 정의하십시오.


비밀은 unicode(r) 실제로 __str__() 자체를 호출되지 않는 것입니다. 대신 __unicode__() 메소드를 찾고 있습니다. __unicode__()의 기본 구현은 __str__()을 호출 한 다음 ascii charset을 사용하여 디코딩을 시도합니다. 인코딩을 전달하면 unicode()은 첫 번째 개체가 디코딩 될 수있는 것으로 예상됩니다. 즉, basestring의 인스턴스입니다. 그것이 내가 'UTF-8'을 통과하지 않는 경우 ASCII로 디코딩하려고하기 때문에


행동이 이상해. 나는 통과한다면 'UTF-8'이 ... 당신이 지정하는 경우 "UTF-8", 그것은 디코딩 할 문자열과 같은 객체로 첫 번째 매개 변수를 취급하기 때문이다

을 다른 오류를 제공합니다. 이를 사용하지 않으면 매개 변수를 유니 코드로 강제 변환 할 객체로 취급합니다.

나는 혼란을 이해하지 못한다. 객체의 text 속성이 항상 UTF-8로 인코딩된다는 것을 알고 있다면 __unicode__()을 정의하면 모든 것이 올바르게 작동합니다.

+0

나는 내가 나 자신을 분명히하지 않았을 것이라고 생각한다. 나는 그것을 안다. 내 말은 유니 코드 (r)가 유니 코드 (r, 'utf-8')와 다른 동작을하는 이유를 아는 것입니다. ??? – nosklo

+0

'utf-8'을 전달하지 않으면 ascii로 디코딩하려고하기 때문에 동작이 이상합니다. 하지만 'utf-8'을 통과하면 다른 오류가 발생합니다 ... – nosklo