我被告知要调用print obj
会调用obj.__str__()
,而print obj.__str__()
print obj.__repr__()
会返回一个字符串以打印到控制台。现在我遇到了Unicode的问题,我无法打印任何非ascii字符。我得到了典型的“ascii超出范围”的东西。
在尝试以下工作时:
__str__()
两个函数完全相同(self.__repr__()
只返回print obj
)。什么行不通:
__str__()
仅在使用ascii范围之外的字符时才会出现问题。最终解决方案是return self.__repr__().encode(sys.stdout.encoding)
:
cp850
现在它适用于所有部件。我现在的问题是:区别在哪里?为什么现在有效?如果没有任何效果我会得到,为什么现在这样。但为什么只有顶部工作,而不是底部。
操作系统是Windows 7 x64,带有默认的Windows命令提示符。此外,编码报告为str(obj)
。这是理解python的一般问题。我的问题已经解决了,但我并不是百分之百满意,主要是因为现在调用# -*- coding: utf-8 -*-
class Sample(object):
def __init__(self):
self.name = u"üé"
def __repr__(self):
return self.name
def __str__(self):
return self.name
obj = Sample()
print obj.__str__(), obj.__repr__(), obj
会产生一个不按我想要的方式编码的字符串。
obj
删除最后一个UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
并且它有效。保持它并与它崩溃
{{1}}
答案 0 :(得分:4)
我的猜测是,对于要打印的对象obj
,打印会执行以下操作:
obj
是否为unicode
。如果是,则将其编码为sys.stdout.encoding
并打印。obj
是否为str
。如果是这样,请直接打印。obj
是其他内容,请拨打str(obj)
并打印出来。第1步是print obj.__str__()
适用于您的情况。
现在,str(obj)
做的是:
obj.__str__()
。str
,请将其返回unicode
,则将其编码为"ascii"
并返回直接调用obj.__str__()
会跳过步骤2-3,这就是您无法解决编码问题的原因。
问题不是由print
的工作方式引起的,而是由str()
的工作方式引起的。 str()
忽略sys.stdout.encoding
。由于它不知道你想对结果字符串做什么,所以它使用的默认编码可以被认为是任意的; ascii
与任何选择一样好或坏。
要防止此错误,请确保从str
返回__str__()
,因为文档要求您这样做。可以用于Python 2.x的模式可能是:
class Foo():
def __unicode__(self):
return u'whatever'
def __str__(self):
return unicode(self).encode(sys.stdout.encoding)
(如果你确定除了打印到控制台之外什么都不需要str()
表示。)
答案 1 :(得分:1)
首先,如果您查看the online documentation,__str__
和__repr__
有不同的目的,应创建不同的输出。因此,从__repr__
调用__str__
并非最佳解决方案。
其次,print
将调用__str__
并且不会期望接收非ascii字符,因为,print
无法猜测如何转换非ascii字符。
最后,在Python 2.x的最新版本中,__unicode__
是为对象创建字符串表示的首选方法。 Python str versus unicode中有一个有趣的解释。
所以,要尝试真正回答这个问题,你可以这样做:
class Sample(object):
def __init__(self):
self.name = u"\xfc\xe9"
# No need to implement __repr__. Let Python create the object repr for you
def __str__(self):
return unicode(self).encode('utf-8')
def __unicode__(self):
return self.name