如何在不引发 UnicodeEncodeError 的情况下覆盖 str 函数?
How do I override the str function without raising a UnicodeEncodeError?
我很困惑,为 class 定义 __str__
似乎对在 class 实例上使用 str
函数没有影响。例如,我在 Django 文档中读到:
The print
statement and the str
built-in call __str__()
to determine the human-readable representation of an object.
但这似乎不是真的。这是一个模块的示例,其中 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
函数?
对于 Python 2,您从 __str__
方法中 return 输入了错误的类型。您正在 returning unicode
,而您 必须 return str
:
def __str__(self):
if six.PY3:
return str(self._text)
else:
return self._text.encode('utf8')
因为 self._text
还不是 str
类型,您需要对其进行编码。因为您 return 改用 Unicode,Python 被迫首先对其进行编码,但默认的 ASCII 编码无法处理非 ASCII é
字符。
打印对象导致正确的输出只是因为我的终端被配置为处理 UTF-8:
>>> a = Test(u'café')
>>> str(a)
'caf\xc3\xa9'
>>> print a
café
>>> unicode(a)
u'caf\xe9'
注意Python3中没有__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,并且只为 [=14] 定义一个 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.
获得相同的装饰器
我很困惑,为 class 定义 __str__
似乎对在 class 实例上使用 str
函数没有影响。例如,我在 Django 文档中读到:
The
str
built-in call__str__()
to determine the human-readable representation of an object.
但这似乎不是真的。这是一个模块的示例,其中 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
函数?
对于 Python 2,您从 __str__
方法中 return 输入了错误的类型。您正在 returning unicode
,而您 必须 return str
:
def __str__(self):
if six.PY3:
return str(self._text)
else:
return self._text.encode('utf8')
因为 self._text
还不是 str
类型,您需要对其进行编码。因为您 return 改用 Unicode,Python 被迫首先对其进行编码,但默认的 ASCII 编码无法处理非 ASCII é
字符。
打印对象导致正确的输出只是因为我的终端被配置为处理 UTF-8:
>>> a = Test(u'café')
>>> str(a)
'caf\xc3\xa9'
>>> print a
café
>>> unicode(a)
u'caf\xe9'
注意Python3中没有__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,并且只为 [=14] 定义一个 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.