在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)
>>>
答案 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