gpt4 book ai didi

python - 打印对象和 unicode,背后是什么?好的指导方针是什么?

转载 作者:太空狗 更新时间:2023-10-29 22:28:07 27 4
gpt4 key购买 nike

我正在为打印和 unicode 转换而苦苦挣扎。这是在 2.5 windows 解释器中执行的一些代码。

>>> import sys
>>> print sys.stdout.encoding
cp850
>>> print u"é"
é
>>> print u"é".encode("cp850")
é
>>> print u"é".encode("utf8")
├®
>>> print u"é".__repr__()
u'\xe9'

>>> class A():
... def __unicode__(self):
... return u"é"
...
>>> print A()
<__main__.A instance at 0x0000000002AEEA88>

>>> class B():
... def __repr__(self):
... return u"é".encode("cp850")
...
>>> print B()
é

>>> class C():
... def __repr__(self):
... return u"é".encode("utf8")
...
>>> print C()
├®

>>> class D():
... def __str__(self):
... return u"é"
...
>>> print D()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 0: ordinal not in range(128)

>>> class E():
... def __repr__(self):
... return u"é"
...
>>> print E()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 0: ordinal not in range(128)

因此,当打印 unicode 字符串时,调用和打印的不是 __repr__() 函数。
但是当打印对象时 __str__()__repr__() (如果 __str__ 未实现)被调用,而不是 __unicode__() 。两者都不能返回 unicode 字符串。
但为什么?为什么如果 __repr__()__str__() 返回一个 unicode 字符串,它的行为不应该与我们打印 unicode 字符串时的行为相同吗?我换句话说:为什么 print D() 不同于 print D().__str__()

我错过了什么吗?

这些示例还表明,如果要打印用 unicode 字符串表示的对象,则必须将其编码为对象字符串(str 类型)。但是为了 pretty-print (避免“├®”),它依赖于 sys.stdout 编码。
那么,我是否必须为每个 __str____repr__ 方法添加 u"é".encode(sys.stdout.encoding) ?或者返回 repr(u"é")?如果我使用管道怎么办?编码是否与 sys.stdout 相同?

我的主要问题是使一个类“可打印”,即 print A() 打印出完全可读的内容(不使用\x*** unicode 字符)。这是需要修改的不良行为/代码:

class User(object):
name = u"Luiz Inácio Lula da Silva"
def __repr__(self):
# returns unicode
return "<User: %s>" % self.name
# won't display gracefully
# expl: print repr(u'é') -> u'\xe9'
return repr("<User: %s>" % self.name)
# won't display gracefully
# expl: print u"é".encode("utf8") -> print '\xc3\xa9' -> ├®
return ("<User: %s>" % self.name).encode("utf8")

谢谢!

最佳答案

Python 对给定的函数和方法没有许多语义类型约束,但它有一些,这是其中之一:__str__(在 Python 2.* 中)必须返回一个字节字符串。像往常一样,如果在需要字节字符串的地方找到了一个 unicode 对象,则应用当前默认编码(通常是 'ascii')来尝试从有问题的 unicode 对象生成所需的字节字符串.

对于这个操作,任何给定文件对象的编码(如果有的话)是无关紧要的,因为从 __str__ 返回的内容可能即将被打印,或者可能会被完全不同的和不相关的治疗。您调用 __str__目的与调用本身及其结果无关;通常,Python 在确定操作的语义时不会考虑操作的“ future 上下文”(操作完成后您将如何处理结果)。

那是因为 Python 并不总是知道您 future 的意图,它会尽量减少惊喜。 打印 str(x)s = str(x); print s(一口气与两口气执行的相同操作),尤其必须具有相同的效果;如果是第二种情况,如果 str(x) 不能有效地产生字节串(即,例如,x.__str__() 不能), 因此在其他情况下也应该出现异常。

print 本身(我相信从 2.4 开始),当出现一个 unicode 对象时,会考虑目标流的 .encoding 属性(如果有的话)(默认情况下 sys.stdout);其他操作,尚未连接到任何给定的目标流,不会 - 而 str(x)(即 x.__str__())就是这样的操作。

希望这有助于说明让您烦恼的行为的原因...

编辑:OP 现在澄清了“我的主要问题是使一个类“可打印”,即 print A() 打印出完全可读的内容(不使用\x*** unicode 字符) ”。以下是我认为最适合该特定目标的方法:

import sys

DEFAULT_ENCODING = 'UTF-8' # or whatever you like best

class sic(object):

def __unicode__(self): # the "real thing"
return u'Pel\xe9'

def __str__(self): # tries to "look nice"
return unicode(self).encode(sys.stdout.encoding or DEFAULT_ENCODING,
'replace')

def __repr__(self): # must be unambiguous
return repr(unicode(self))

也就是说,这种方法侧重于 __unicode__ 作为类实例格式化自身的主要方式——但是因为(在 Python 2 中)print 调用 __str__ 相反,它有一个委托(delegate)给 __unicode__ 在编码方面它可以做到最好。并不完美,但是 Python 2 的 print 语句无论如何都远非完美;-)。

__repr__ 就其本身而言,必须努力明确,即以冒风险为代价“看起来不错”歧义(理想情况下,如果可行,它应该返回一个字节字符串,如果将其传递给 eval,将使实例等于当前实例......这远非总是可行,但没有歧义是 __str____repr__ 之间区别的绝对核心,我强烈建议尊重这种区别!)。

关于python - 打印对象和 unicode,背后是什么?好的指导方针是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3557095/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com