Python __str__与__unicode__


213

有没有时,你应该实现一个python约定__str__()__unicode__()。我已经看到类重写的__unicode__()频率高于,__str__()但似乎不一致。当实施一个相对于另一个更好时,是否有特定的规则?实施这两种方法是否必要/良好做法?

Answers:


257

__str__()是旧方法-它返回字节。__unicode__()是新的首选方法-它返回字符。名称有些混乱,但是在2.x中,出于兼容性原因,我们坚持使用它们。通常,您应该将所有字符串格式都放在中__unicode__(),并创建一个存根__str__()方法:

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

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


2
你是说同时创建unicodestr方法,还是仅将字符串保留在_(u“”)中并创建字符串(不使用unicode方法)?
muntu 2010年

12
仅实施其中之一会有什么陷阱吗?当您仅实现__unicode__然后执行时会发生什么str(obj)
RickyA

9
unicodeNameError在Python 3上引发一个简单的模式,该模式可同时在2和3上使用吗?
bradley.ayers

1
future软件包还提供了@ bradley.ayers,python_2_unicode_compatible而无需将Django作为依赖项。
蒙克皮特

1
这取决于。因为python3不使用unicode而是使用str ;)来表示python 2 unicode
Eddwin Paz

23

如果我不特别关心给定类的微优化字符串化,那么我将始终__unicode__只实施它,因为它更笼统。当我确实关心此类微小的性能问题(这是例外,不是规则)时,__str__仅(当我可以证明在字符串化输出中绝不会出现非ASCII字符时)或两者(当两者都可能时)可能会救命。

我认为这些是牢固的原则,但实际上知道这是很常见的,只有ASCII字符会不做任何努力来证明它(例如,字符串形式只有数字,标点符号,并且可能是短的ASCII名称;-)在这种情况下,直接采用“公正__str__”方法是很典型的做法(但如果我与一个编程团队合作,提出了一项本地准则来避免这种情况,我将对该提案+1,因为在这些问题上很容易犯错,并且“过早的优化是编程中万恶之源” ;-)。


2
在python 2.6.2中,我最近绊倒了,因为特定的内置Exception子类的实例使用str(e)和unicode(e)给出了不同的结果。str(e)提供了用户友好的输出;unicode(e)提供了不同的,用户不友好的输出。这被视为越野车行为吗?该类是UnicodeDecodeError; 为了避免造成混淆,我没有预先命名它-异常与unicode相关的事实并不特别相关。
Paul Du Bois 2012年

13

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


8

如果您在Django中同时使用python2和python3,则建议使用python_2_unicode_compatible装饰器:

Django提供了一种简单的方法来定义可在Python 2和3上使用的str()和 unicode()方法,您必须定义一个返回文本的str()方法并应用python_2_unicode_compatible()装饰器。

如前面对另一个答案的注释中所述,某些版本的future.utils也支持此装饰器。在我的系统上,我需要为python2安装一个新的future模块,并为python3安装future。之后,这是一个功能示例:

#! /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__

3

Python 2: 仅实现__str __(),并返回unicode。

什么时候__unicode__()省略,有人打电话unicode(o)u"%s"%o,Python的呼叫o.__str__()并转换为Unicode使用系统编码。(请参阅的文档__unicode__()。)

相反的说法是不正确的。如果实施__unicode__()但未__str__(),则当有人调用str(o)或时"%s"%o,Python返回repr(o)


基本原理

为什么unicode要从中返回a__str__()
如果__str__()返回unicode,Python会自动str使用系统编码将其转换为。

有什么好处?
①它使您不必担心系统编码是什么(即locale.getpreferredencoeding(…))。就个人而言,这不仅麻烦,而且我认为系统无论如何都要注意这一点。②如果小心,您的代码可能会与Python 3相互兼容,其中__str__()返回unicode。

从名为的函数中返回unicode是骗人的 __str__()
一点。但是,您可能已经在这样做了。如果你有from __future__ import unicode_literals位于文件的顶部,则很有可能在不知道的情况下返回unicode。

那么Python 3呢?
Python 3不使用__unicode__()。但是,如果您实现__str__()了使其在Python 2或Python 3下返回unicode的功能,那么那部分代码将是交叉兼容的。

如果我想unicode(o)与之有本质区别str()怎么办?
同时实现__str__()(可能返回str)和__unicode__()。我想这很少见,但您可能希望获得实质上不同的输出(例如,特殊字符的ASCII版本,例如":)"for u"☺")。

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


1

值得向那些不熟悉该__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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.