我们如何获得__repr __()的默认行为?

时间:2018-02-13 22:52:34

标签: python python-3.x representation repr

如果有人在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>

3 个答案:

答案 0 :(得分:20)

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

答案 1 :(得分:10)

注意,最好的答案可能只是直接使用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>'
>>>

答案 2 :(得分:9)

通常情况下,我们可以使用 object.__repr__ ,但这将是#em>每个项目的&#34;对象代理,因此:

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

由于intobject,但__repr__覆盖。

如果您想要一个级别的覆盖,我们可以使用super(..)

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

对于int,这又意味着我们将打印<int object at ...>,但如果我们将int作为子类,那么它将使用__repr__ { {1}}再次,如:

int

然后它看起来像:

class special_int(int):

    def __repr__(self):
        return 'Special int'

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

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

但通常无论如何都要打破压倒一切。程序员重写函数的原因是更改行为。不尊重这种情况当然有时会产生一些有用的功能,但通常会导致代码合同不再满足。例如,如果程序员覆盖s,他/她也将覆盖super(..),如果您使用另一个类的哈希值和真实__eq__,那么事情就会开始破坏。

直接调用魔术函数也经常被视为反模式,所以你最好也避免这样做。