__repr__() 函数的最佳输出类型和编码实践?
Posted
技术标签:
【中文标题】__repr__() 函数的最佳输出类型和编码实践?【英文标题】:Best output type and encoding practices for __repr__() functions? 【发布时间】:2011-04-07 08:49:12 【问题描述】:最近,我在__repr__()
、format()
和编码方面遇到了很多麻烦。 __repr__()
的输出应该编码还是 unicode 字符串? 在 Python 中,__repr__()
的结果是否有最佳编码?我要输出的确实有非 ASCII 字符。
我使用 Python 2.x,并且想编写可以轻松适应 Python 3 的代码。程序因此使用
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function # The 'Hello' literal represents a Unicode object
以下是一些一直困扰我的其他问题,我正在寻找解决这些问题的解决方案:
-
应该可以打印到 UTF-8 终端(我将
sys.stdout.encoding
设置为 UTF-8
,但最好是其他情况也可以)。
将输出通过管道传输到文件(以 UTF-8 编码)应该可以工作(在这种情况下,sys.stdout.encoding
是 None
)。
我的许多__repr__()
函数的代码目前有很多return ….encode('utf-8')
,这很重。有什么坚固而轻便的东西吗?
在某些情况下,我什至有像return ('<>'.format(repr(x).decode('utf-8'))).encode('utf-8')
这样的丑陋野兽,即对象的表示被解码,放入格式化字符串,然后重新编码。我想避免这种复杂的转换。
为了编写简单的__repr__()
函数,在这些编码问题上表现得很好,您建议做什么?
【问题讨论】:
【参考方案1】:在 Python2 中,__repr__
(和 __str__
)必须返回一个字符串对象,而不是
Unicode 对象。在Python3中,情况正好相反,__repr__
和__str__
必须返回 unicode 对象,而不是字节(née 字符串)对象:
class Foo(object):
def __repr__(self):
return u'\NWHITE SMILING FACE'
class Bar(object):
def __repr__(self):
return u'\NWHITE SMILING FACE'.encode('utf8')
repr(Bar())
# ☺
repr(Foo())
# UnicodeEncodeError: 'ascii' codec can't encode character u'\u263a' in position 0: ordinal not in range(128)
在 Python2 中,您真的别无选择。您必须为
__repr__
的返回值。
顺便问一下,你读过PrintFails wiki吗?它可能不会直接回答 你的其他问题,但我确实发现它有助于阐明为什么 发生错误。
使用from __future__ import unicode_literals
时,
'<>'.format(repr(x).decode('utf-8'))).encode('utf-8')
可以更简单的写成
str('<>').format(repr(x))
假设str
在您的系统上编码为utf-8
。
没有from __future__ import unicode_literals
,表达式可以写成:
'<>'.format(repr(x))
【讨论】:
@EOL, 返回值必须是字符串对象。是你指向的参考手册页如何表达返回值必须是@987654336实例的约束@(unicode 对象不会是“字符串对象”)。repr
通常预计只返回 ascii(对于所有 unicode 对象,repr(uo)
的东西,例如:即使 that 只返回 ascii - 我认为没有内置 - in 或标准库类型的行为不同)但严格来说这不是语言限制,因此它不是参考手册的业务。建议的文档补丁总是受欢迎的,顺便说一句!-)
@Alex:感谢 cmets。我想我的困惑来自一个事实,即在 Python 2.x 中也说“Unicode 字符串”:这就是为什么我想知道 __repr__()
是否也可以返回一个 Unicode 字符串......我一直考虑提交文档补丁。 :)
@EOL,是的,我发现与字符串相关的术语(“字符串”、“unicode 字符串”、“原始字符串”……)不幸的是,在普通话语中存在歧义的风险——我 尝试始终使用严格不含歧义的术语,例如“str instance”、“unicode object”、“rawstring literal”等,但有时这种严格的术语会让人觉得生硬在非正式场合。在语言参考中,不幸的“unicode 字符串”唯一出现在 2.4.1(文字)的单个段落中:s/string/object/ 那里和“字符串”变得明确在语言参考中 i>(重要的地方)。
语言参考也有可能是故意模棱两可的,因为它不应该只是CPython的参考,但对于 all 符合 Python 实现:在 Jython 和 IronPython 中,我们非常热衷于考虑完全符合的实现,all 字符串都是 Unicode(而且成本很高,而且完全反对他们各自的平台,以其他方式制作东西)。也许我们确实需要一个补充的 CPython 实现特定参考,作为实现中立的 Language 参考的附加。
当然,str('<>').format(repr(x))
也可以使用...见***.com/questions/809796/…【参考方案2】:
我使用如下函数:
def stdout_encode(u, default='UTF8'):
if sys.stdout.encoding:
return u.encode(sys.stdout.encoding)
return u.encode(default)
那么我的__repr__
函数如下所示:
def __repr__(self):
return stdout_encode(u'<MyClass 0 1>'.format(self.abcd, self.efgh))
【讨论】:
【参考方案3】:我认为装饰者可以以理智的方式管理__repr__
的不兼容性。这是我使用的:
from __future__ import unicode_literals, print_function
import sys
def force_encoded_string_output(func):
if sys.version_info.major < 3:
def _func(*args, **kwargs):
return func(*args, **kwargs).encode(sys.stdout.encoding or 'utf-8')
return _func
else:
return func
class MyDummyClass(object):
@force_encoded_string_output
def __repr__(self):
return 'My Dummy Class! \NWHITE SMILING FACE'
【讨论】:
漂亮的装饰器;不过,我对其进行了修改,以便在不需要时不定义_func
。因此,根据您的代码,Python 2 中的__repr__
显然可以返回一个Unicode 字符串(可能是因为unicode_literals
?)。这与 unutbu 的答案相冲突……我发现文档含糊不清(docs.python.org/2/reference/datamodel.html#object.__repr__,docs.python.org/2/reference/lexical_analysis.html#index-14)。我会对这方面的任何参考信息感兴趣,只是为了确保__repr__
返回一个 Unicode 字符串不会出现不可预见的问题。
@EOL 那么,Python 2 中的__repr__
显然可以返回一个 Unicode 字符串 (...) 你为什么这么认为?
不错,我的错。我将删除我之前的评论,因为它不相关。以上是关于__repr__() 函数的最佳输出类型和编码实践?的主要内容,如果未能解决你的问题,请参考以下文章
SQLAlchemy 为大型表定义 __repr__ 的最佳方法
python 的print和特殊方法 __str__和__repr__