what's the difference between unicode(self) and self.__unicode__() in a Python Class?
在处理unicode问题时,我发现
1 2 3 4 5 6 7 8 9 10 11 12 13 | #-*- 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 |
上面的代码工作正常,但是如果我把
1 | UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128) |
有问题的代码是:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #-*- 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 |
我很好奇python如何处理这个问题,尝试了dis模块,但没有看到太多不同之处:
1 2 3 4 5 | Disassembly of __str__: 12 0 LOAD_FAST 0 (self) 3 LOAD_ATTR 0 (__unicode__) 6 CALL_FUNCTION 0 9 RETURN_VALUE |
VS
1 2 3 4 5 | Disassembly of __str__: 10 0 LOAD_GLOBAL 0 (unicode) 3 LOAD_FAST 0 (self) 6 CALL_FUNCTION 1 9 RETURN_VALUE |
从您的
清楚地说:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | 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) ??↓ |
简单解决:让
1 2 | s = u'中文' return s.encode('utf-8') |
这将返回非Unicode字节字符串。这就是
我们需要一些术语。编码就是使用某种编码方式获取一个Unicode字符串并生成一个表示它的字节字符串。解码是相反的:取一个字节字符串(我们认为它编码一个Unicode字符串),并使用指定的编码将其解释为Unicode字符串。
当我们编码到一个字节字符串,然后使用相同的编码进行解码时,我们会得到原来的Unicode。
有时,当您调用
使事情变得更加复杂,在python2中,
(顺便说一下,这一切的工作方式完全不同——更清楚地说,imho——在python3中。)
同样,当
(实际上,您可以通过传递第二个参数来覆盖
所以,现在我们可以解决这个问题了。
问题:我们希望
解决方案:直接在
1 2 3 4 5 6 | class test(): def __unicode__(self): return u'中文' def __str__(self): return unicode(self).encode('utf-8') |
当您定义
btw,
在python对象上调用
由于您没有指定应该使用什么编码,您会得到一个错误,即参数不能只用ASCII来表示。
当您使用
您可以使用所需的编码作为
1 | unicode( str,"utf-8" ) |
这应该和你的