更新时间:2022-05-24 22:36:04
添加了新的魔法 super()
行为以避免违反 D.R.Y.(不要重复自己)原则,请参阅 PEP 3135.必须通过将类作为全局引用来显式命名类也容易出现与 super()
本身相同的重新绑定问题:
The new magic super()
behaviour was added to avoid violating the D.R.Y. (Don't Repeat Yourself) principle, see PEP 3135. Having to explicitly name the class by referencing it as a global is also prone to the same rebinding issues you discovered with super()
itself:
class Foo(Bar):
def baz(self):
return super(Foo, self).baz() + 42
Spam = Foo
Foo = something_else()
Spam().baz() # liable to blow up
这同样适用于使用类装饰器,其中装饰器返回一个新对象,该对象重新绑定类名:
The same applies to using class decorators where the decorator returns a new object, which rebinds the class name:
@class_decorator_returning_new_class
class Foo(Bar):
def baz(self):
# Now `Foo` is a *different class*
return super(Foo, self).baz() + 42
神奇的 super()
__class__
单元通过让您访问原始类对象很好地回避了这些问题.
The magic super()
__class__
cell sidesteps these issues nicely by giving you access to the original class object.
PEP 由 Guido 启动,他最初设想super
成为关键字,以及使用单元格查找当前类的想法也是他的.当然,将其作为关键字的想法是 初稿的一部分PEP.
The PEP was kicked off by Guido, who initially envisioned super
becoming a keyword, and the idea of using a cell to look up the current class was also his. Certainly, the idea to make it a keyword was part of the first draft of the PEP.
然而,实际上是 Guido 本人随后 走开了从关键字想法太神奇",改为提出当前的实现.他预计 super()
可能是个问题:
However, it was in fact Guido himself who then stepped away from the keyword idea as 'too magical', proposing the current implementation instead. He anticipated that using a different name for super()
could be a problem:
我的补丁使用了一个中间解决方案:它假设你需要 __class__
每当您使用名为 'super'
的变量时.因此,如果您(全球)将 super
重命名为 supper
并使用 supper
而不是 super
,它将不起作用没有参数(但如果你传递它,它仍然可以工作__class__
或实际的类对象);如果你有一个不相关的名为 super
的变量,一切正常,但方法将使用用于单元格变量的调用路径稍慢.
My patch uses an intermediate solution: it assumes you need
__class__
whenever you use a variable named'super'
. Thus, if you (globally) renamesuper
tosupper
and usesupper
but notsuper
, it won't work without arguments (but it will still work if you pass it either__class__
or the actual class object); if you have an unrelated variable namedsuper
, things will work but the method will use the slightly slower call path used for cell variables.
所以,最后是 Guido 自己宣称使用 super
关键字感觉不对,而提供一个神奇的 __class__
单元格是可以接受的折衷方案.
So, in the end, it was Guido himself that proclaimed that using a super
keyword did not feel right, and that providing a magic __class__
cell was an acceptable compromise.
我同意实现的神奇隐式行为有点令人惊讶,但 super()
是该语言中应用最多的函数之一.看看所有误用的 super(type(self), self)
或 super(self.__class__, self)
在 Internet 上找到的调用;如果曾经从派生类中调用过任何代码 你会得到一个无限递归异常.至少简化的 super()
调用没有参数,避免了 那个 问题.
I agree that the magic, implicit behaviour of the implementation is somewhat surprising, but super()
is one of the most mis-applied functions in the language. Just take a look at all the misapplied super(type(self), self)
or super(self.__class__, self)
invocations found on the Internet; if any of that code was ever called from a derived class you'd end up with an infinite recursion exception. At the very least the simplified super()
call, without arguments, avoids that problem.
至于重命名的super_
;只需在您的方法中引用 __class__
,它就会再次起作用.如果您在方法中引用 super
或 __class__
名称,则会创建单元格:
As for the renamed super_
; just reference __class__
in your method as well and it'll work again. The cell is created if you reference either the super
or __class__
names in your method:
>>> super_ = super
>>> class A(object):
... def x(self):
... print("No flipping")
...
>>> class B(A):
... def x(self):
... __class__ # just referencing it is enough
... super_().x()
...
>>> B().x()
No flipping