【问题标题】:When do you need to pass arguments to python super()?什么时候需要将参数传递给 python super()?
【发布时间】:2019-12-31 02:00:28
【问题描述】:

python 中的 super() 内置函数的一个用例是调用一个被覆盖的方法。下面是一个使用super()调用Parent类的echo函数的简单例子:

class Parent():
    def echo(self):
        print("in Parent")

class Child(Parent):
    def echo(self):
        super().echo()
        print("in Child")

我见过将 2 个参数传递给 super() 的代码。在这种情况下,签名看起来像super(subClass, instance),其中subClass 是调用super() 的子类,instance 是调用的实例,即self。所以在上面的例子中,super() 行会变成:

super(Child, self).echo()

查看python3 docs,这两个用例在从类内部调用时是相同的。

是否从 python3 开始完全弃用使用 2 个参数调用 super()?如果仅在调用重写函数时不推荐使用此方法,您能否举例说明为什么其他情况需要它们?

我也很想知道为什么 python 需要这两个参数?在 python3 中进行super() 调用时是否会注入/评估它们,还是在这种情况下不需要它们?

【问题讨论】:

    标签: python python-3.x inheritance super


    【解决方案1】:

    如果您不传递参数,Python 3 会努力为您提供它们。这有点笨拙,但它通常有效。本质上,它只是假设您的方法的第一个参数是selfsuper 的第二个参数),并且当类定义完成时,它为引用super 或@987654324 的任何函数提供一个虚拟闭包范围@ 将 __class__ 定义为您刚刚定义的类,因此 no-arg super() 可以检查堆栈帧以找到 __class__ 作为第一个参数。

    这通常有效,但在某些情况下无效:

    • staticmethods 中(因为第一个参数实际上不是类),虽然staticmethods 不应该以同样的方式参与继承层次结构,所以这并不完全出乎意料。

    • 在将 *args 作为第一个参数的函数中(这是实现任何接受任意关键字参数的方法的唯一安全方法,例如 3.8 之前的 dict 子类,当它们引入仅位置参数时) .

    • 如果 super 调用在嵌套范围内,这可以是隐式的,例如生成器表达式,或任何类型的理解(listsetdict),因为嵌套范围不直接附加到类,所以它没有得到 __class__ 定义方法的魔法附加到类本身获取。

    在极少数情况下,您可能希望显式绕过特定类来解析父方法,在这种情况下,您需要在 MRO 中显式传递一个与默认情况下会拉取的类不同的类.这是一种深奥而可怕的魔法,所以我不推荐它,但我认为我有理由这样做一次。

    所有这些都是相对罕见的情况,所以大多数时候,对于纯粹针对 Python 3 的代码,你可以使用无参数 super,并且只有在你 无论什么原因都不能使用它。 No-arg super 更干净、更快,并且在实时开发过程中可能更正确(如果你替换 MyClass,旧的实例该类的版本将缓存旧版本,并且 no-arg super 将继续工作,在您的全局变量中手动查找它会找到该类的新版本并爆炸),所以尽可能使用它。

    【讨论】:

      【解决方案2】:

      在 Python 3 中,带有零参数的 super() 已经是 super(__class__, self) 的快捷方式。完整的解释见PEP3135

      这不是 Python 2 的情况,所以我猜你发现的大多数代码示例实际上都是为 Python 2(或 Python2+3 兼容)编写的

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-01
        • 2016-11-26
        • 2011-09-20
        • 1970-01-01
        • 2011-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多