super().__ repr __()和repr(super())有什么区别?

时间:2018-11-24 01:37:15

标签: python python-3.x class super repr

在python(3.5.2)中,我期望repr(obj)函数调用__repr__()类的魔术方法obj。 但是,调用它们两者似乎不会产生相同的结果。谁能解释为什么?

示例代码

class parent:

    def __init__(self):
        self.a = "haha"

    def __repr__(self):
        return repr(self.a)

class child(parent):
    def __init__(self):
        super().__init__()
        self.b="bebe"

    def __repr__(self):
        return "("+super().__repr__()+", "+repr(super())+", "+self.b+")"

    def print1(self):
        print("super().__repr__() returns:", super().__repr__())
        print("repr(super()) returns:", repr(super()))
        print("plom(super()).__repr__() returns:", plom(super()).__repr__())
        print("repr(plom(super())) returns:", repr(plom(super())))

def plom(var):
    return var

t=child()
print(t.__repr__())
print(repr(t))
print('-----')
t.print1()
print('-----')
print(plom(t).__repr__())
print(repr(plom(t)))

结果:

>>> 
 RESTART: test super.py 
('haha', <super: <class 'child'>, <child object>>, bebe)
('haha', <super: <class 'child'>, <child object>>, bebe)
-----
super().__repr__() returns: 'haha'
repr(super()) returns: <super: <class 'child'>, <child object>>
plom(super()).__repr__() returns: 'haha'
repr(plom(super())) returns: <super: <class 'child'>, <child object>>
-----
('haha', <super: <class 'child'>, <child object>>, bebe)
('haha', <super: <class 'child'>, <child object>>, bebe)
>>> 

3 个答案:

答案 0 :(得分:3)

调用repr(super())直接访问__repr__ 类上的super(从技术上讲,是C tp_repr结构的PyTypeObject定义super类型)。当隐式调用大多数dunder方法时,其行为方式都是这样(与将其显式调用为方法相反)。 repr(x)不等同于x.__repr__()。您可以将repr定义为:

def repr(obj):
    return type(obj).__repr__(obj)  # Call unbound function of class with instance as arg

您期望的是:

def repr(obj):
    return obj.__repr__()  # Call bound method of instance

此行为是故意的;一是按实例自定义dunder方法几乎没有意义,二是禁止它允许在C级别使用效率更高的代码(它具有执行上述说明性方法的更快方法)。

通过对比,super().__repr__()super 实例上查找方法,并且super定义了自定义tp_getattro(大致等同于定义自定义__getattribute__方法),这意味着实例上的查找在找到类的tp_repr / __repr__之前会被拦截,而是通过自定义属性getter(执行超类委派)。

答案 1 :(得分:1)

如果您咨询 the docs,将会看到super返回了一个代理对象,该代理对象根据方法解析顺序将方法调用委托给适当的类。

因此repr(super())为您提供代理对象的表示形式。而方法调用super().__repr__()为您提供了由下一个类按方法解析顺序定义的表示形式。

如果您想要超类本身,请尝试

my_object.__mro__[1]

答案 2 :(得分:0)

super().__repr__()中,您要调用超级对象的repr类,以便获得'haha'

在第二个中,您将调用super()的repr。 super()输出什么? <super: <class 'child'>, <child object>>,因此您可以有效地在某些类层次结构上调用repr