关于python:如何为类对象创建自定义字符串表示?

How to create a custom string representation for a class object?

考虑这个类:

1
2
class foo(object):
    pass

默认的字符串表示形式如下所示:

1
2
>>> str(foo)
"<class '__main__.foo'>"

如何使此显示成为自定义字符串?


在类的元类中实现__str__()__repr__()

1
2
3
4
5
6
7
8
class MC(type):
  def __repr__(self):
    return 'Wahaha!'

class C(object):
  __metaclass__ = MC

print C

使用__str__如果您指的是可读的字符串化,请使用__repr__进行明确的表示。


1
2
3
4
5
class foo(object):
    def __str__(self):
        return"representation"
    def __unicode__(self):
        return u"representation"


如果您必须在__repr____str__之间进行选择,请选择第一个,因为默认情况下,__str__在未定义时调用__repr__

自定义vector3示例:

1
2
3
4
5
6
7
8
9
10
11
class Vector3(object):
    def __init__(self, args):
        self.x = args[0]
        self.y = args[1]
        self.z = args[2]

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

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

在本例中,repr再次返回一个可以直接使用/执行的字符串,而str作为调试输出更有用。

1
2
3
v = Vector3([1,2,3])
print repr(v)    #Vector3([1,2,3])
print str(v)     #Vector(x:1, y:2, z:3)


伊格纳西奥·瓦兹奎兹·艾布拉姆斯的回答是完全正确的。然而,它来自于Python2代。对当前python 3的更新是:

1
2
3
4
5
6
7
8
class MC(type):
  def __repr__(self):
    return 'Wahaha!'

class C(object, metaclass=MC):
    pass

print(C)

如果您希望代码同时运行在python 2和python 3上,那么六个模块已经介绍了:

1
2
3
4
5
6
7
8
9
10
11
from __future__ import print_function
from six import with_metaclass

class MC(type):
  def __repr__(self):
    return 'Wahaha!'

class C(with_metaclass(MC)):
    pass

print(C)

最后,如果您有一个想要定制静态repr的类,那么上面基于类的方法非常有效。但是如果你有几个类,你就必须为每个类生成一个类似于MC的元类,这会让人厌烦。在这种情况下,进一步执行元编程并创建一个元类工厂会使事情变得更清晰:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from __future__ import print_function
from six import with_metaclass

def custom_class_repr(name):
   """
    Factory that returns custom metaclass with a class ``__repr__`` that
    returns ``name``.
   """

    return type('whatever', (type,), {'__repr__': lambda self: name})

class C(with_metaclass(custom_class_repr('Wahaha!'))): pass

class D(with_metaclass(custom_class_repr('Booyah!'))): pass

class E(with_metaclass(custom_class_repr('Gotcha!'))): pass

print(C, D, E)

印刷品:

1
Wahaha! Booyah! Gotcha!

元编程并不是你每天都需要的东西,但是当你需要它的时候,它真的很到位!


在所有的答案中,我的版本加上装饰:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from __future__ import print_function
import six

def classrep(rep):
    def decorate(cls):
        class RepMetaclass(type):
            def __repr__(self):
                return rep

        class Decorated(six.with_metaclass(RepMetaclass, cls)):
            pass

        return Decorated
    return decorate


@classrep("Wahaha!")
class C(object):
    pass

print(C)

标准输出:

1
Wahaha!

下边:

  • 没有超级类(没有class C:)不能声明C
  • C实例将是一些奇怪派生的实例,因此为这些实例添加__repr__可能也是一个好主意。