在Python website上找到的关于super()
的文档说,它返回一个代理对象,将方法调用委托给父类或同级类。在super considered super、how does super() work with multiple inheritance 和super considered harmful中找到的信息解释了实际上使用了mro
中的下一个方法。我的问题是,如果使用super(object, self).some_method()
会发生什么?由于object
通常出现在mro
列表的末尾,因此我猜搜索会立即到达末尾并出现异常。但事实上,似乎代理本身的方法被调用了,如super(object, self).__repr__()
所示,它显示了超级对象本身。我想知道super()
和object
的行为是否根本不是委托方法。
如果是这样的话,我想知道是否有可靠的材料提到过它,以及它是否适用于其他Python实现。你知道吗
class X(object):
def __init__(self):
# This shows [X, object].
print X.mro()
# This shows a bunch of attributes that a super object can have.
print dir(super(object, self))
# This shows something similar to <super object at xxx>
print(object, self)
# This failed with `super() takes at least one argument`
try:
super(object, self).__init__()
except:
pass
# This shows something like <super <class 'object'>, <'X' object>>.
print(super(object, self).__repr__())
# This shows the repr() of object, like <'X' object at xxx>
print(super(X, self).__repr__())
if __name__ == '__main__':
X()
super
定义了它自己的一些属性,并且需要一种方法来提供对它们的访问。首先是使用__dunder__
样式,Python为自己保留了这种样式,并且说任何库或应用程序都不应该定义以双下划线开头和结尾的名称。这意味着super
对象可以确信没有任何东西会与它的__self__
、__self_class__
和__thisclass__
属性冲突。因此,如果它搜索mro,但没有找到请求的属性,那么它会返回到试图在超级对象本身上找到属性。例如:因为您已经指定了
object
作为要开始查看的类型,而且object
始终是mro中的最后一个类型,所以没有可能的候选对象来获取方法或属性。在这种情况下,super的行为就好像它尝试了各种类型来查找名称,但没有找到名称一样。所以它试图从自身获取属性。但是,由于super
对象也是一个对象,因此它可以访问__init__
、__repr__
以及object
定义的所有其他对象。因此super
为您返回它自己的__init__
和__repr__
方法。你知道吗这是一种“问一个愚蠢的问题(超级),得到一个愚蠢的答案”的情况。也就是说,
super
应该只使用第一个参数作为定义函数的类来调用。当你用object
调用它时,你得到的是未定义的行为。你知道吗如果
super
在查看要委托给的方法解析顺序(MRO)时没有找到某个对象(或者如果您正在查找属性__class__
),它将检查自己的属性。你知道吗因为
object
始终是MRO中的最后一种类型(至少据我所知,它始终是最后一种类型),所以您有效地禁用了委托,它将只检查超级实例。你知道吗我发现这个问题非常有趣,所以我去了} (in CPython 3.6.5) ),我把它(粗略地)翻译成纯Python,并附上了我自己的一些附加注释:
super
的源代码,特别是委托部分(^{如您所见,有一些方法可以用来查找
super
上的属性:__class__
属性object
作为第一个参数)!你知道吗__getattribute__
在剩余的MRO中找不到匹配项。你知道吗实际上,因为它的工作方式类似于
super
,所以可以改用它(至少就属性委托而言):它将从
MySuper.__repr__
打印hoho
。通过插入一些print
来跟随控制流,您可以自由地对代码进行实验。你知道吗我上面所说的是基于我对cpython3.6源代码的观察,但是我认为对于其他Python版本来说应该没有太大区别,因为其他Python实现(通常)都遵循CPython。你知道吗
事实上,我还检查了:
它们都返回
super
的__repr__
。你知道吗请注意,Python遵循“我们都是同意的成年人”的风格,因此如果有人费心将这种不寻常的用法形式化,我会感到惊讶。我的意思是,谁会试图委托给
object
(“最终”父类)的兄弟类或父类的方法。你知道吗相关问题 更多 >
编程相关推荐