【问题标题】:How can we get the default behavior of __repr__()?我们如何获得 __repr__() 的默认行为?
【发布时间】:2018-07-24 10:12:59
【问题描述】:

如果有人在 python 中编写了一个类,但没有指定他们自己的 __repr__() 方法,那么会为他们提供一个默认的方法。但是,假设我们要编写一个与默认__repr__() 具有相同或相似行为的函数。但是,我们希望此函数具有默认 __repr__() 方法的行为,即使该类的实际 __repr__() 已重载。也就是说,假设我们要编写一个与默认__repr__() 具有相同行为的函数,而不管是否有人重载了__repr__() 方法。我们该怎么做?

class DemoClass:
    def __init__(self):
        self.var = 4
    def __repr__(self):
        return str(self.var)

def true_repr(x):
    # [magic happens here]
    s = "I'm not implemented yet"
    return s

obj = DemoClass()

print(obj.__repr__())

print(true_repr(obj))

期望的输出:

print(obj.__repr__()) 打印 4,但 print(true_repr(obj)) 打印类似:
<__main__.DemoClass object at 0x0000000009F26588>

【问题讨论】:

    标签: python python-3.x representation repr


    【解决方案1】:

    通常我们可以为此使用 object.__repr__,但这将用于“每个项的对象代表,因此:

    >>> object.__repr__(4)
    '<int object at 0xa6dd20>'
    

    因为intobject,但__repr__ 被覆盖。

    如果你想上一层覆盖,我们可以使用super(..):

    >>> super(type(4), 4).__repr__()  # going up one level
    '<int object at 0xa6dd20>'
    

    对于int,这又意味着我们将打印&lt;int object at ...&gt;,但是如果我们将例如子类化int,那么它将再次使用int__repr__,例如:

    class special_int(int):
    
        def __repr__(self):
            return 'Special int'
    

    然后会是这样的:

    >>> s = special_int(4)
    >>> super(type(s), s).__repr__()
    '4'
    

    我们在这里所做的是用super(..) 创建一个代理 对象。 Super 将遍历对象的方法解析顺序 (MRO),并尝试找到覆盖该函数的第一个函数(来自 s 的超类)。如果我们使用单继承,那是覆盖该函数的最接近的父级,但如果它涉及到一些多重继承,那么这就更棘手了。因此,我们选择该父级的__repr__,并调用该函数。

    这也是super 的一个相当奇怪的应用,因为通常这个类(这里是type(s))是一个固定的,并且 依赖于s 本身的类型,因为否则多次这样的super(..) 调用将导致无限循环。

    但通常无论如何打破覆盖都是一个坏主意。程序员重写函数的原因是改变行为。不尊重这一点当然有时会导致一些有用的功能,但通常会导致代码合约不再满足。例如,如果一个程序员重写了__eq__,他/她也将重写__hash__,如果你使用另一个类的哈希,以及真正的__eq__,那么事情就会开始崩溃。

    直接调用魔法函数也经常被视为一种反模式,所以你最好也避免这种情况。

    【讨论】:

    • 这里的问题是“默认__repr__”的直观概念可能并不真正意味着提问者想要它的意思。 (此外,我通常会否决任何建议将type 的输出传递给super 的内容,但在这里可能有意义。不过,它需要更多关于孙子类的警告。)
    【解决方案2】:

    注意,正如其他人指出的那样,最好的答案可能只是直接使用object.__repr__。但是可以大致实现相同的功能:

    >>> def true_repr(x):
    ...     type_ = type(x)
    ...     module = type_.__module__
    ...     qualname = type_.__qualname__
    ...     return f"<{module}.{qualname} object at {hex(id(x))}>"
    ...
    

    所以....

    >>> A()
    hahahahaha
    >>> true_repr(A())
    '<__main__.A object at 0x106549208>'
    >>>
    

    【讨论】:

    【解决方案3】:

    您可以使用object.__repr__(obj)。这是可行的,因为默认的repr 行为是在object.__repr__ 中定义的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-10
      • 2017-04-13
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多