Python 在 __str__ 中出现“序号超出范围”错误,但在 print 中没有
我有一个对象,它可以从一个JSON文件中读取一些数据。这个JSON数据里有些字符串包含拉丁1字符,比如:
"name" : "frisée"
我把这个对象转换成一个表格,里面包含从JSON对象中读取的一些字符串。如果我这样写:
def __str__(self): # Never mind the details, what matters is that I use __str__
ts = [p + (count,) for p, count in self.counts.items()]
ts.sort(key=lambda x:(x[2], x[0], x[1]))
return "\n".join(["%s\t%s\t%s" % (t[0], t[1], t[2]) for t in ts])
然后尝试运行 print MyObject()
,我就会遇到错误:
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 9112: ordinal not in range(128)
但是如果我这样写:
def to_string(self):
ts = [p + (count,) for p, count in self.counts.items()]
ts.sort(key=lambda x:(x[2], x[0], x[1]))
return "\n".join(["%s\t%s\t%s" % (t[0], t[1], t[2]) for t in ts])
然后运行 print MyObject().to_string()
,一切就正常了。字符"é"也能正确显示。
为什么 __str__
的表现和 to_string
不一样呢?我该怎么做才能让 __str__
版本也能正确打印出来?
我尝试了各种不同的 encode
方法,但都没有成功。
1 个回答
1
你的 __str__
方法返回的是一种 unicode
类型的值,而 JSON 字符串总是 Unicode 格式的。不过,__str__
的返回值必须 始终 是 字节串,也就是 str
类型。如果你不这样做,Python 会自动帮你调用 str()
,这就意味着它会用默认的 ASCII 编码来处理任何 Unicode 字符。
你可以明确地对结果进行编码:
def __str__(self):
ts = [p + (count,) for p, count in self.counts.items()]
ts.sort(key=lambda x:(x[2], x[0], x[1]))
return u'\n'.join([u'\t'.join(t[:2]) for t in ts]).encode('utf8')
或者可以使用 __unicode__
方法。不过,这个方法不会被 print
自动调用;你需要明确地使用 print unicode(MyObject())
来调用它。
如果你的终端设置正确,print
知道如何正确编码 unicode
字符串。它会使用 sys.stdout.encoding
来明确地编码你的 Unicode 数据。这就是为什么 MyObject().to_string()
能正常工作的原因。