Python __str__与__unicode__

时间:2009-08-20 15:34:08

标签: python string unicode conventions

是否应该实施__str__()__unicode__()的python约定。我见过的课程比__unicode__()更频繁地覆盖__str__(),但似乎并不一致。当一个与另一个相比更好的时候是否有特定的规则?是否有必要/良好做法实施两者?

6 个答案:

答案 0 :(得分:250)

__str__()是旧方法 - 它返回字节。 __unicode__()是新的首选方法 - 它返回字符。名字有点令人困惑,但在2.x中,出于兼容性原因,我们坚持使用它们。通常,您应将所有字符串格式设置为__unicode__(),并创建存根__str__()方法:

def __str__(self):
    return unicode(self).encode('utf-8')

在3.0中,str包含字符,因此相同的方法名为__bytes__()__str__()。这些行为符合预期。

答案 1 :(得分:22)

如果我不特别关心给定类的微优化字符串化,我总是只实现__unicode__,因为它更通用。当我关心这些微小的性能问题(这是例外,而不是规则)时,只有__str__(当我能证明字符串输出中永远不会有非ASCII字符时)或两者都有(当两者都有时)可能),可能有帮助。

我认为这些是坚实的原则,但在实践中,知道除了ASCII字符之外什么也没有做任何努力来证明它是非常普遍的(例如,字符串形式只有数字,标点符号,也许是一个简短的ASCII名称; - )在这种情况下,直接转向“公正__str__”方法是非常典型的(但如果我与之合作的编程团队提出了一个避免这种情况的本地指南,那么我对该提案的评分为+1,在这些问题上很容易犯错并且“过早优化是编程中所有邪恶的根源”; - )。

答案 2 :(得分:13)

随着世界变得越来越小,您遇到的任何字符串最终都可能包含Unicode。因此,对于任何新应用,您至少应提供__unicode__()。您是否也覆盖__str__()只是一个品味问题。

答案 3 :(得分:4)

如果您在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__

答案 4 :(得分:0)

值得指出的是那些不熟悉__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

答案 5 :(得分:0)

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"☺")。

我意识到有些人可能会发现这个争议。