super()
通常依赖编译器提供__class__
闭包单元,即绑定到派生方法的类对象。闭包在您使用名称的那一刻创建super()
在方法中(或者如果您使用__class__
):
>>> class Foo(object):
... def bar(self):
... super() # just using super or __class__ is enough
...
>>> Foo.bar.__closure__[0].cell_contents
<class '__main__.Foo'>
>>> Foo.bar.__closure__[0].cell_contents is Foo
True
该关闭让super()
无参数工作(self
参数取自本地名称空间)。
然而,attr
生成一个新类对象当您指定要使用时__slots__
;你不能在事后向类中添加插槽,所以创建新的类对象 https://github.com/python-attrs/attrs/blob/4faf5f9c265fe9cd093ff6f866d63c1b2962b91b/src/attr/_make.py#L382-L394它取代了你装饰的那个。
封闭件附于meth
是原来的预装饰类,与新生成的类不是同一个类对象:
>>> Derived.meth.__closure__[0].cell_contents
<class '__main__.Derived'>
>>> Derived.meth.__closure__[0].cell_contents is Derived
False
这打破了预期super()
有,因此无法使用 0 参数变体。这super(Derived, self)
变体显式查找名称Derived
作为全局调用时,找到新生成的类,所以有效。
我将详细介绍如何super()
没有参数的作品,以及为什么,在为什么 Python 3.x 的 super() 如此神奇? https://stackoverflow.com/questions/19608134/why-is-python-3-xs-super-magic/19609168#19609168
这被报道为问题 #102 https://github.com/python-attrs/attrs/issues/102在跟踪器中,并且fixed通过改变一些封闭ctypes hackery https://github.com/python-attrs/attrs/blob/master/src/attr/_compat.py#L98-L101。此修复将成为即将发布的 17.3 版本的一部分。