【问题标题】:How to define a __str__ method for a class?如何为类定义 __str__ 方法?
【发布时间】:2011-11-15 22:23:41
【问题描述】:

在 Python 中,object 类充当所有(新式)类的根超类。至少默认情况下,将strrepr 应用于object 的任何子类的“类实例”会产生相同的结果:

>>> class spam(object): pass
... 
>>> str(spam)
"<class '__main__.spam'>"
>>> str(spam) == repr(spam)

我想定义一个object 的子类,比如fancyobject,它在各方面都与object 相同,除了将strrepr 应用于fancyobject 本身会产生不同的输出:

>>> class ham(fancyobject): pass
...
>>> str(ham)
'ham'
>>> repr(ham)
"<class '__main__.ham'>"

有没有办法在 Python 中做到这一点?

PS:我知道__str__ 特殊方法,但我的理解是如果类A 覆盖__str__,那么只有在@ 的实例上调用str 时才会调用覆盖方法987654337@,而不是在 A 本身上调用它时。即:

>>> class A(object):
...     def __str__(self):
...         return 'from new __str__: ' + object.__str__(self)
... 
>>> str(A())
'from new __str__: <__main__.A object at 0x7f79c62a5310>'
>>> str(A)
"<class '__main__.A'>"

【问题讨论】:

    标签: python


    【解决方案1】:

    实际上与对象实例相同的机制适用于类型。类型只是对象本身,因此通过调用 他们的 类型的__str__() 方法将它们转换为字符串,这称为“元类”。所以你必须覆盖元类上的__str__() 方法:

    class fancytype(type):
        def __str__(self):
            return self.__name__
    class ham(object):
        __metaclass__ = fancytype
    print ham
    

    打印

    ham
    

    【讨论】:

    • 有人知道 Python 3.3 及更高版本(应该)如何改变这一点吗?
    • @JürgenA.Erhard 在我写这篇文章的时候(在 Python 3.3 发布之前),当时 Python 的当前开发版本已将 str(some_type) 的结果更改为简单的 some_type.__name__。显然,此更改从未发布到版本中,目前我找不到任何参考。我会从答案中删除评论。
    【解决方案2】:

    你也可以像这样为整个模块设置默认元类

    class fancytype(type):
        def __str__(self):
            return self.__name__
    
    __metaclass__ = fancytype
    
    class ham:
        pass
    print ham
    

    【讨论】:

    • 谢谢,这很有趣,但在我看来它只适用于“经典”类。我看不出这种技术如何影响object 的新型类(直接或间接继承)。
    • @kjo:嗯,这个例子中的ham类会自动变成新式类,因为fancytype派生自type,这是新式类的类型。从ham 派生的所有内容也将是fancytype
    • 谢谢,很高兴知道;到目前为止,我一直认为定义新样式类的唯一方法是在 class ham(...): 语句的 (...) 子句中显式包含 object 或其某些子类。
    【解决方案3】:

    这是 Python 3 的新答案。基本上,您将元类作为关键字参数传递给类定义。

    class fancytype(type):
        def __str__(self):
            return self.__name__
    class ham(metaclass=fancytype):
        pass
    print(ham)
    

    打印

    ham
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-27
      • 1970-01-01
      • 1970-01-01
      • 2012-11-04
      相关资源
      最近更新 更多