본문 바로가기

개발하자

유니코드(자체)와 자체의 차이점은 무엇인가요.파이썬 클래스의 __유니코드__()?

반응형

유니코드(자체)와 자체의 차이점은 무엇인가요.파이썬 클래스의 __유니코드__()?

유니코드 문제를 처리하는 동안, 나는 그것을 발견했고 다른 동작을 가지고 있다:

#-*- coding:utf-8 -*-
import sys
import dis
class test():
    def __unicode__(self):
        s = u'中文'
        return s.encode('utf-8')

    def __str__(self):
        return self.__unicode__()
print dis.dis(test)
a = test()
print a

위 코드는 정상적으로 작동하지만 로 변경하면 오류가 표시됩니다:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

문제가 있는 코드는 다음과 같습니다:

#-*- coding:utf-8 -*-
import sys
import dis
class test():
    def __unicode__(self):
        s = u'中文'
        return s.encode('utf-8')

    def __str__(self):
        return unicode(self)
print dis.dis(test)
a = test()
print a

파이썬이 이것을 어떻게 처리하는지 매우 궁금합니다. 모듈 해제를 시도했지만 많은 차이를 보지 못했습니다:

Disassembly of __str__:
 12           0 LOAD_FAST                0 (self)
              3 LOAD_ATTR                0 (__unicode__)
              6 CALL_FUNCTION            0
              9 RETURN_VALUE   

Disassembly of __str__:
 10           0 LOAD_GLOBAL              0 (unicode)
              3 LOAD_FAST                0 (self)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE       



당신은 당신의 방법에서 돌아옵니다.

분명히 하기 위해:

In [18]: class Test(object):
    def __unicode__(self):
        return u'äö↓'.encode('utf-8')
    def __str__(self):
        return unicode(self)
   ....:     

In [19]: class Test2(object):
    def __unicode__(self):
        return u'äö↓'
    def __str__(self):
        return unicode(self)
   ....:     

In [20]: t = Test()

In [21]: t.__str__()
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
/home/dav1d/<ipython-input-21-e2650f29e6ea> in <module>()
----> 1 t.__str__()

/home/dav1d/<ipython-input-18-8bc639cbc442> in __str__(self)
      3         return u'äö↓'.encode('utf-8')
      4     def __str__(self):
----> 5         return unicode(self)
      6 

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

In [22]: unicode(t)
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
/home/dav1d/<ipython-input-22-716c041af66e> in <module>()
----> 1 unicode(t)

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

In [23]: t2 = Test2()

In [24]: t2.__str__()
Out[24]: u'\xe4\xf6\u2193'

In [25]: str(_) # _ = last result
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
/home/dav1d/<ipython-input-25-3a1a0b74e31d> in <module>()
----> 1 str(_) # _ = last result

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)'

In [26]: unicode(t2)
Out[26]: u'\xe4\xf6\u2193'

In [27]: class Test3(object):
def __unicode__(self):
    return u'äö↓'
def __str__(self):
    return unicode(self).encode('utf-8')
....:     

In [28]: t3 = Test3()

In [29]: t3.__unicode__()
Out[29]: u'\xe4\xf6\u2193'

In [30]: t3.__str__()
Out[30]: '\xc3\xa4\xc3\xb6\xe2\x86\x93'

In [31]: print t3
äö↓

In [32]: print unicode(t3)
äö↓

또는 내 경우에는 반환을 기대하는 사람들이 당신에게 반환을 허용하여 작동하지 않는 사람을 인코딩하려고 할 것이다.

쉬운 수정: 유니코드와 바이트를 반환합니다.




Python 개체를 호출할 때 출력은 메서드에 전달하는 인수의 유니코드 표현입니다.

사용할 인코딩을 지정하지 않았기 때문에 ASCII만 사용하여 인수를 표현할 수 없다는 오류가 발생합니다.

당신이 사용할 때 당신은 그 문자열을 인코딩하기 위해 utf-8을 사용해야 한다고 지정하는 것인데, 이는 정확하고 문제없이 발생한다.

원하는 인코딩을 다음과 같은 메서드의 두 번째 매개 변수로 사용할 수 있습니다:

unicode( str, "utf-8" )

그리고 그것은 당신의 방법과 같은 방식으로 작동할 것이다.




특수 방법을 정의할 때 사용할 인코딩을 지정했습니다. 단순히 전화를 걸 때 인코딩을 지정하지 않았기 때문에 파이썬은 기본 "ascii"를 사용했습니다.

그건 그렇고 유니코드가 아닌 바이트 문자열을 반환해야 합니다. 바이트 문자열이 아닌 유니코드를 반환해야 합니다. 그래서 이 코드는 거꾸로 되어 있습니다. 유니코드를 반환하지 않기 때문에 파이썬은 아마도 기본 인코딩을 사용하여 변환하려고 할 것이다.




s = u'中文'
return s.encode('utf-8')

유니코드가 아닌 바이트 문자열을 반환합니다. 그것이 바로 그것이다. utf-8은 마법으로 데이터를 유니코드로 바꾸는 것이 아니다; 만약 있다면, 그 반대이다 - 유니코드(추상)를 바이트(데이터, 더 많거나 덜함)로 표현하는 방식.

우리는 여기서 약간의 용어가 필요하다. To는 유니코드 문자열을 가져다가 어떤 종류의 인코딩을 사용하여 그것을 바이트 문자열로 만드는 것이다. To는 그 반대입니다. 바이트 문자열(유니코드 문자열을 인코딩한다고 생각됨)을 지정된 인코딩을 사용하여 유니코드 문자열로 사용합니다.

바이트 문자열로 인코딩한 다음 동일한 인코딩을 사용하여 디코딩하면 원래 유니코드를 다시 얻습니다.

하나의 가능한 인코딩입니다. 훨씬 더 많아요.

가끔 파이썬은 당신이 전화하면 a를 보고할 것이다. 왜? 왜냐하면 당신은 바이트 문자열을 시도하기 때문이다. 이 프로세스의 적절한 입력은 유니코드 문자열이므로 파이썬은 먼저 바이트 문자열을 유니코드로 시도합니다. 하지만 그것은 어떤 코덱을 사용해야 할지 모르기 때문에 그것은 가정한다. 이 코덱은 모든 종류의 데이터를 수신할 수 있는 환경에서 가장 안전한 선택입니다. 단순히 바이트 > = 128에 대한 오류를 보고하며, 이는 다양한 8비트 인코딩에서 수많은 다른 방식으로 처리됩니다. (아주 옛날에 Mac에서 PC로 또는 그 반대의 문자가 있는 워드 파일을 가져오려고 했던 것을 기억하십니까? 플랫폼 내장 인코딩이 달랐기 때문에 다른 컴퓨터에서 이상한 기호를 얻을 수 있습니다.)

파이썬 2에서는 유니코드를 해석하는 것과는 무관한 다른 깔끔한 것들을 구현하기 위해 / 메커니즘을 사용한다. 예를 들어, Base64 인코더가 있으며, 문자열 탈출 시퀀스를 자동으로 처리하는 것이 있다(즉, 백슬래시가 변경되고 그 다음에 't'자가 탭으로 변경됨). 이러한 "인코딩" 또는 "디코딩" 중 일부는 바이트 문자열에서 바이트 문자열로, 또는 유니코드에서 유니코드로 변환됩니다.

()

마찬가지로, 바이트 문자열을 반환할 때 (스타일의 문제로) 파이썬 내장 함수는 자동으로 다음과 같이 디코딩하고, 유니코드 문자열을 반환할 때 (다시) 로 인코딩한다. 이것은 당신이 통제할 수 없는 코드에서 막후에서 발생한다. 하지만, 당신은 그들이 하기로 되어 있는 것을 고치고 할 수 있다.

실제로 두 번째 매개 변수를 전달하여 에 대한 인코딩을 재정의할 수 있습니다. 그러나 유니코드 문자열이 이미 에서 반환되어 있기 때문에 여기서는 잘못된 해결책입니다. 그리고 인코딩 매개 변수를 사용하지 않으므로 운이 없습니다.)

자, 이제 우리는 문제를 해결할 수 있습니다.

문제: 유니코드 문자열을 반환하고 -인코딩된 버전을 반환하고자 합니다.

해결책: 에서 직접 문자열을 반환하고, 에서 명시적으로 인코딩을 수행합니다:

class test():
    def __unicode__(self):
        return u'中文'

    def __str__(self):
        return unicode(self).encode('utf-8')

반응형