我很困惑,为类定义__str__
似乎对在类实例上使用str
函数没有影响。例如,我在Django文档中读到:
str
内置调用__str__()
,用于确定对象的人类可读表示。
但这似乎并非如此。这是一个模块中的示例,其中text
始终被假定为unicode:
import six
class Test(object):
def __init__(self, text):
self._text = text
def __str__(self):
if six.PY3:
return str(self._text)
else:
return unicode(self._text)
def __unicode__(self):
if six.PY3:
return str(self._text)
else:
return unicode(self._text)
在Python 2中,它提供了以下行为:
>>> a=Test(u'café')
>>> print a.__str__()
café
>>> print a # same error with str(a)
---------------------------------------------------------------------------
UnicodeEncodeError Traceback (most recent call last)
<ipython-input-63-202e444820fd> in <module>()
----> 1 str(a)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 3: ordinal not in range(128)
有没有办法重载str
函数?
答案 0 :(得分:5)
对于Python 2,您从__str__
方法返回了错误的类型。您将返回unicode
,而必须返回str
:
def __str__(self):
if six.PY3:
return str(self._text)
else:
return self._text.encode('utf8')
由于self._text
尚未属于str
类型,因此您需要对其进行编码。因为您返回了Unicode,所以Python必须先对其进行编码,但默认的ASCII编码无法处理非ASCII é
字符。
打印对象会导致右输出,因为我的终端配置为处理UTF-8:
>>> a = Test(u'café')
>>> str(a)
'caf\xc3\xa9'
>>> print a
café
>>> unicode(a)
u'caf\xe9'
请注意,Python 3中有 no __unicode__
方法;您在该方法中的if six.PY3
完全是多余的。以下也适用:
class Test(object):
def __init__(self, text):
self._text = text
def __str__(self):
if six.PY3:
return self._text
else:
return self._text.encode('utf8')
def __unicode__(self):
return self._text
但是,如果您使用的是six
库,那么使用@six.python_2_unicode_compatible
decorator要好得多,并且只为__str__
方法定义Python 3版本:
@six.python_2_unicode_compatible
class Test(object):
def __init__(self, text):
self._text = text
def __str__(self):
return self._text
假设text
始终是Unicode。如果您正在使用Django,那么您可以从django.utils.encoding
module获得相同的装饰器。