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

Too*_*one 15 python repr representation python-3.x

如果有人在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))
Run Code Online (Sandbox Code Playgroud)

期望的输出:

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

int*_*ser 23

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


jua*_*aga 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))}>"
...
Run Code Online (Sandbox Code Playgroud)

所以....

>>> A()
hahahahaha
>>> true_repr(A())
'<__main__.A object at 0x106549208>'
>>>
Run Code Online (Sandbox Code Playgroud)

  • 漂亮!不知道“__qualname__”,它是最近添加的吗? (2认同)
  • @cᴏʟᴅsᴘᴇᴇᴅ:相对较新;`__qualname__` 在版本 3.3 中添加:http://legacy.python.org/dev/peps/pep-3155/ (2认同)

Wil*_*sem 9

通常我们可以使用object.__repr__它,但这将是" 每个项目的对象repr ,因此:

>>> object.__repr__(4)
'<int object at 0xa6dd20>'
Run Code Online (Sandbox Code Playgroud)

既然int是一个object,但有__repr__覆盖.

如果你愿意,可以去一个重写的水平,我们可以使用super(..):

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

对于一个int,如此又意味着我们将打印<int object at ...>,但如果我们将举例子类int,那么它将使用__repr__int再次,如:

class special_int(int):

    def __repr__(self):
        return 'Special int'
Run Code Online (Sandbox Code Playgroud)

然后它看起来像:

>>> s = special_int(4)
>>> super(type(s), s).__repr__()
'4'
Run Code Online (Sandbox Code Playgroud)

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

这也是一个相当奇怪的应用程序super,因为通常是类(这里type(s))是固定一个,一点依赖于的类型s本身,否则多个这样的super(..)电话会导致一个无限循环.

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

直接调用魔术函数也经常被视为反模式,所以你最好也避免使用它.