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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4932438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 18:12:32  来源:igfitidea点击:

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

pythonclass

提问by Bj?rn Pollex

Consider this class:

考虑这个类:

class foo(object):
    pass

The default string representation looks something like this:

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

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

How can I make this display a custom string?

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

采纳答案by Ignacio Vazquez-Abrams

Implement __str__()or __repr__()in the class's metaclass.

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

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

class C(object):
  __metaclass__ = MC

print C

Use __str__if you mean a readable stringification, use __repr__for unambiguous representations.

使用__str__,如果你说的是可读的字串,使用__repr__了明确的表示。

回答by Andrey Gubarev

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

回答by user1767754

If you have to choose between __repr__or __str__go for the first one, as by default implementation __str__calls __repr__when it wasn't defined.

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

Custom Vector3 example:

自定义 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)

In this example, reprreturns again a string that can be directly consumed/executed, whereas stris more useful as a debug output.

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

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

回答by Jonathan Eunice

Ignacio Vazquez-Abrams' approved answeris quite right. It is, however, from the Python 2 generation. An update for the now-current Python 3 would be:

Ignacio Vazquez-Abrams 认可的答案是正确的。然而,它来自 Python 2 代。现在的 Python 3 的更新将是:

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

class C(object, metaclass=MC):
    pass

print(C)

If you want code that runs across both Python 2 and Python 3, the sixmodule has you covered:

如果您想要在 Python 2 和 Python 3 上运行的代码,六个模块为您提供:

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)

Finally, if you have one class that you want to have a custom static repr, the class-based approach above works great. But if you have several, you'd have to generate a metaclass similar to MCfor each, and that can get tiresome. In that case, taking your metaprogramming one step further and creating a metaclass factory makes things a bit cleaner:

最后,如果您有一个类想要自定义静态表示,上面的基于类的方法效果很好。但是如果你有几个,你就必须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)

prints:

印刷:

Wahaha! Booyah! Gotcha!

Metaprogramming isn't something you generally need everyday—but when you need it, it really hits the spot!

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

回答by Aviv Goll

Just adding to all the fine answers, my version with decoration:

只是添加到所有好的答案中,我的装饰版本:

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)

stdout:

标准输出:

Wahaha!

The down sides:

不利的一面:

  1. You can't declare Cwithout a super class (no class C:)
  2. Cinstances will be instances of some strange derivation, so it's probably a good idea to add a __repr__for the instances as well.
  1. C没有超类就不能声明(否class C:
  2. C实例将是一些奇怪派生的实例,因此也__repr__为实例添加 a 可能是个好主意。