Python 如何为类对象创建自定义字符串表示?

Python 如何为类对象创建自定义字符串表示?,python,class,Python,Class,以这一类为例: class foo(object): pass 默认字符串表示形式如下所示: >>> str(foo) "<class '__main__.foo'>" >>str(foo) "" 如何使其显示为自定义字符串?在类的元类中实现或 class foo(object): def __str__(self): return "representation" def __unicode__(self):

以这一类为例:

class foo(object):
    pass
默认字符串表示形式如下所示:

>>> str(foo)
"<class '__main__.foo'>"
>>str(foo)
""
如何使其显示为自定义字符串?

在类的元类中实现或

class foo(object):
    def __str__(self):
        return "representation"
    def __unicode__(self):
        return u"representation"
class MC(type):
  def __repr__(self):
    return 'Wahaha!'

class C(object):
  __metaclass__ = MC

print C

使用
\uuuu str\uuuu
如果您指的是可读的字符串化,请使用
\uuuu repr\uuuu
进行明确的表示。

如果您必须在
\uuuuu repr\uuu
\uuu str\uuuu
之间进行选择,则使用第一个字符串化,因为默认情况下,
\uuuu str uuuuu
在未定义时调用
\uuuuu repr\uuuu

自定义矢量3示例:

class Vector3(object):
    def __init__(self, args):
        self.x = args[0]
        self.y = args[1]
        self.z = args[2]

    def __repr__(self):
        return "Vector3([{0},{1},{2}])".format(self.x, self.y, self.z)

    def __str__(self):
        return "x: {0}, y: {1}, z: {2}".format(self.x, self.y, self.z)
在本例中,
repr
再次返回可以直接使用/执行的字符串,而
str
作为调试输出更有用

v = Vector3([1,2,3])
print repr(v)    #Vector3([1,2,3])
print str(v)     #x:1, y:2, z:3
这是非常正确的。然而,它来自Python2一代。当前Python 3的更新将是:

MC类(类型):
定义报告(自我):
返回“娃哈哈!”
C类(对象,元类=MC):
通过
印刷品(C)
如果您希望代码同时在Python 2和Python 3上运行,本模块将介绍:

from\uuuuu future\uuuuu导入打印功能
从六个导入,使用_元类
MC类(类型):
定义报告(自我):
返回“娃哈哈!”
C类(含_元类(MC)):
通过
印刷品(C)
最后,如果您有一个类需要定制静态repr,那么上面基于类的方法非常有效。但如果有几个元类,则必须为每个元类生成一个类似于
MC
的元类,这可能会让人厌烦。在这种情况下,进一步进行元编程并创建元类工厂会使事情变得更清晰:

from\uuuuu future\uuuuu导入打印功能
从六个导入,使用_元类
def自定义_类_报告(名称):
"""
返回自定义元类的工厂,其类为
返回“`name`”。
"""
返回类型('whatever',(type,),{lambda self:name})
C类(带元类(自定义类报告('Wahaha!')):通过
D类(带元类(自定义类报告('Booyah!')):通过
类E(带有元类(自定义类报告('Gotcha!')):通过
打印(C、D、E)
印刷品:

娃哈哈!糟糕!明白了!
元编程并不是你每天都需要的东西,但是当你需要它的时候,它真的很到位

除了所有的好答案,我的装饰版:

from\uuuuu future\uuuuu导入打印功能
进口六
def类代表(代表):
def装饰(cls):
类RepMetaclass(类型):
定义报告(自我):
退货代表
课堂装饰(六个,带有_元类(RepMetaclass,cls)):
通过
回报
返修
@classrep(“娃哈哈!”)
C类(对象):
通过
印刷品(C)
标准:

娃哈哈! 不利方面:

  • 如果没有超类(没有
    类C:
    ),就不能声明
    C
  • C
    实例将是一些奇怪派生的实例,因此为实例添加一个
    \uuuu repr\uuu
    可能也是一个好主意

  • 这将更改类的
    实例
    的字符串表示形式,而不是类本身的字符串表示形式。抱歉,没有看到文章的第二部分。使用上面的方法。@RobertSiemer为什么?虽然他的回答并没有特别针对OP的问题,但仍然很有帮助。它帮助了我。乍一看,我没有看到任何关于实例实现的问题。因此,人们可能会首先进入这个页面。我想创建某种类型的类装饰器,这样我就可以轻松地为我的类设置自定义字符串表示,而无需为每个类编写元类。我不太熟悉Python的元类,所以你能给我一些提示吗?不幸的是,这不能用类装饰器来完成;定义类时必须设置它。@Space\u C0wb0y:您可以向类正文中添加一个类似于
    \u表示法
    的字符串,然后
    返回self.\u表示法
    在元类的
    \u repr\uu()方法中。@BjörnPollex您可以使用decorator,但我认为你必须与语言的许多微妙之处作斗争。即使您这样做了,您仍然必须以这样或那样的方式使用元类,因为您不想使用默认的
    \uuuu repr\uuuu
    来表示
    C
    。拥有
    \u表示
    成员的另一种选择是创建一个元类工厂,用适当的
    \uuuuuu repr\uuuu
    生成一个元类(如果您经常使用它,这可能会很好)。@ThomasLeonard:虽然您关于
    \uuuu repr\uuuu
    \uuu str uu
    的观点是正确的,但这并没有回答实际问题,这是关于类对象,而不是实例的。感谢您的反馈,我们完全监督了这一点。让我回顾一下我的答案。我认为repr和str的实现已经互换了。