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

时间:2011-02-08 11:27:12

标签: python class metaprogramming metaclass

考虑这个课程:

class foo(object):
    pass

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

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

如何将此显示设为自定义字符串?

5 个答案:

答案 0 :(得分:232)

在班级的元类中实施__str__()__repr__()

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

class C(object):
  __metaclass__ = MC

print C

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

答案 1 :(得分:19)

class foo(object):
    def __str__(self):
        return "representation"
    def __unicode__(self):
        return u"representation"

答案 2 :(得分:9)

如果您必须在__repr____str__之间选择第一个,那么默认情况下,实施__str__会在未定义时调用__repr__

自定义Vector3示例:

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)     #Vector(x:1, y:2, z:3)

答案 3 :(得分:3)

Ignacio Vazquez-Abrams' approved answer是正确的。但是,它来自Python 2代。当前的Python 3的更新为:

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

class C(object, metaclass=MC):
    pass

print(C)

如果您想要同时在Python 2和Python 3上运行的代码,则six模块将涉及以下内容:

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的元类,而这可能会很麻烦。在这种情况下,将元编程再进一步一步并创建一个元类工厂会使事情变得更加整洁:

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)

打印:

Wahaha! Booyah! Gotcha!

元编程不是您通常每天都需要的东西,但是,当您需要它时,它真的很实用!

答案 4 :(得分:0)

只需将所有精美的答案添加到我的带有修饰符的版本中即可:

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)

标准输出:

Wahaha!

缺点:

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