当你应该实现__str__()
与__unicode__()
时,是否存在python约定。我已经看到类比__unicode__()
更频繁地覆盖__str__()
,但它看起来并不一致。当一个与另一个相比更好的时候是否有特定的规则?是否有必要/良好做法同时实施?
__str__()
是旧方法 - 它返回字节。 __unicode__()
是新的首选方法 - 它返回字符。名字有点令人困惑,但在2.x中,出于兼容性原因,我们坚持使用它们。通常,您应该将所有字符串格式设置在__unicode__()
中,并创建一个stub __str__()
方法:
def __str__(self):
return unicode(self).encode('utf-8')
在3.0中,str
包含字符,因此相同的方法被命名为__bytes__()
和__str__()
。这些行为符合预期。
如果我不特别关心给定类的微优化字符串化,我总是只实现__unicode__
,因为它更通用。当我关心这些微小的性能问题(这是例外,而不是规则)时,只有__str__
(当我能证明字符串化输出中不会有非ASCII字符时)或两者都有(当两者都可能时),可能有帮助。
我认为这些是坚实的原则,但在实践中,知道除了ASCII字符之外什么也没有做任何努力来证明它(例如字符串形式只有数字,标点符号,也许是一个简短的ASCII名称;-),这是很常见的。如果直接转向“只是__str__
”方法是很典型的(但如果我合作的编程团队提出了一个避免这种情况的本地指南,我会在提案中获得+1,因为在这些问题上很容易出错)并且“过早优化是编程中所有邪恶的根源”;-)。
随着世界变得越来越小,您遇到的任何字符串最终都可能包含Unicode。所以对于任何新的应用程序,你至少应该提供__unicode__()
。你是否也覆盖__str__()
只是一个品味问题。
如果您在Django中使用python2和python3,我推荐python_2_unicode_compatible装饰器:
Django提供了一种简单的方法来定义适用于Python 2和3的str()和unicode()方法:您必须定义一个str()方法返回文本并应用python_2_unicode_compatible()装饰器。
正如之前对另一个答案的评论中所指出的,future.utils的某些版本也支持这个装饰器。在我的系统上,我需要为python2安装一个更新的未来模块,并为python3安装未来。之后,这是一个功能性的例子:
#! /usr/bin/env python
from future.utils import python_2_unicode_compatible
from sys import version_info
@python_2_unicode_compatible
class SomeClass():
def __str__(self):
return "Called __str__"
if __name__ == "__main__":
some_inst = SomeClass()
print(some_inst)
if (version_info > (3,0)):
print("Python 3 does not support unicode()")
else:
print(unicode(some_inst))
这是示例输出(其中venv2 / venv3是virtualenv实例):
~/tmp$ ./venv3/bin/python3 demo_python_2_unicode_compatible.py
Called __str__
Python 3 does not support unicode()
~/tmp$ ./venv2/bin/python2 demo_python_2_unicode_compatible.py
Called __str__
Called __str__
Python 2:仅实现__str __(),并返回一个unicode。
当省略__unicode__()
并且有人调用unicode(o)
或u"%s"%o
时,Python调用o.__str__()
并使用系统编码转换为unicode。 (见documentation of __unicode__()
。)
反之则不然。如果你实现__unicode__()
而不是__str__()
,那么当有人调用str(o)
或"%s"%o
时,Python会返回repr(o)
。
合理
为什么从unicode
返回__str__()
会有效?
如果__str__()
返回一个unicode,Python会使用系统编码自动将其转换为str
。
有什么好处?
①它让你不必担心系统编码是什么(即locale.getpreferredencoeding(…)
)。个人而言,这不仅是混乱的,而且我认为无论如何系统应该照顾它。 ②如果你小心,你的代码可能会与Python 3交叉兼容,其中__str__()
返回unicode。
从名为__str__()
的函数返回unicode是不是很具有欺骗性?
一点。但是,您可能已经在做了。如果你的文件顶部有from __future__ import unicode_literals
,你很有可能在不知情的情况下返回unicode。
那么Python 3呢?
Python 3不使用__unicode__()
。但是,如果您实现__str__()
以便它在Python 2或Python 3下返回unicode,那么您的代码部分将是交叉兼容的。
如果我希望unicode(o)
与str()
有实质性的不同怎么办?
实施__str__()
(可能返回str
)和__unicode__()
。我想这很少见,但你可能想要实质上不同的输出(例如,特殊字符的ASCII版本,如":)"
的u"☺"
)。
我意识到有些人可能会发现这种争议。
值得指出那些不熟悉__unicode__
功能的人在Python 2.x中使用它的一些默认行为,特别是当与__str__
并排定义时。
class A :
def __init__(self) :
self.x = 123
self.y = 23.3
#def __str__(self) :
# return "STR {} {}".format( self.x , self.y)
def __unicode__(self) :
return u"UNICODE {} {}".format( self.x , self.y)
a1 = A()
a2 = A()
print( "__repr__ checks")
print( a1 )
print( a2 )
print( "\n__str__ vs __unicode__ checks")
print( str( a1 ))
print( unicode(a1))
print( "{}".format( a1 ))
print( u"{}".format( a1 ))
产生以下控制台输出......
__repr__ checks
<__main__.A instance at 0x103f063f8>
<__main__.A instance at 0x103f06440>
__str__ vs __unicode__ checks
<__main__.A instance at 0x103f063f8>
UNICODE 123 23.3
<__main__.A instance at 0x103f063f8>
UNICODE 123 23.3
现在当我取消注释__str__
方法
__repr__ checks
STR 123 23.3
STR 123 23.3
__str__ vs __unicode__ checks
STR 123 23.3
UNICODE 123 23.3
STR 123 23.3
UNICODE 123 23.3