Python 3.x 中的 super() 函数

在 Python 3.x 中,super() 函数可以不带参数调用:
在这里插入图片描述

class A(object):
    def x(self):
         print("Hey now")

class B(A):
    def x(self):
        super().x()

>>> B().x()
Hey now

为了实现这个功能,Python 编译器执行了一些编译时操作,因此,以下代码将引发错误:

super_ = super

class A(object):
    def x(self):
        print("No flipping")

class B(A):
    def x(self):
        super_().x()

>>> B().x()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in x
RuntimeError: super(): __class__ cell not found

为什么 super() 函数在没有编译器的帮助下无法在运行时解析超类?在哪些实际情况下,这种行为或其背后的原因会对粗心的程序员造成困扰?

2、解决方案

添加新的 super() 行为是为了避免违反 DRY(Don’t Repeat Yourself)原则,请参阅 PEP 3135。必须通过引用全局变量显式命名类也容易出现与你用 super() 本身发现的相同重绑定问题:

class Foo(Bar):
    def baz(self):
        return super(Foo, self).baz() + 42

Spam = Foo
Foo = something_else()

Spam().baz()  # 可能引发异常

当装饰器返回一个新对象(它会重新绑定类名)时,使用类装饰器也适用:

@class_decorator_returning_new_class
class Foo(Bar):
    def baz(self):
        # 现在 `Foo` 是一个*不同的类*
        return super(Foo, self).baz() + 42

神奇的 super() class 单元通过让你访问原始类对象很好地规避了这些问题。

PEP 是由 Guido 发起的,他最初设想 super 成为一个关键字,使用单元查找当前类的想法也来自他。当然,将其用作关键字的想法是 PEP 的第一稿的一部分。

然而,事实上,Guido 本人后来放弃了关键字的想法,因为它“太神奇了”,转而提出当前的实现方案。他预见到为 super() 使用不同的名称可能是一个问题:

我的补丁使用了中间解决方案:它假设你每当你使用名为“super”的变量时都需要 class。因此,如果你(全局地)将 super 重命名为 supper 并使用 supper 但不使用 super,它将无法在不带参数的情况下工作(但如果你将 class 或实际类对象传递给它,它仍然会工作);如果你有一个名为 super 的不相关变量,事情会奏效,但该方法将使用用于单元变量的略慢的调用路径。

所以,最后,Guido 本人宣称使用 super 关键字感觉不对,提供一个神奇的 class 单元是一个可以接受的折衷方案。

我同意该实现的魔术隐式行为有些令人惊讶,但 super() 是该语言中最常被误用的函数之一。只需查看 Internet 上找到的所有误用的 super(type(self), self) 或 super(self.class, self) 调用;如果从派生类调用其中任何代码,你最终将得到一个无限递归异常。至少简化的 super() 调用(不带参数)避免了此问题。

至于重命名的 super_;只需在你的方法中引用 class,它将再次起作用。如果你在方法中引用 super 或 class 名称,则创建单元:

>>> 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值