python中超级方法的隐含参数

Posted

技术标签:

【中文标题】python中超级方法的隐含参数【英文标题】:Implied parameters for super method in python 【发布时间】:2021-12-30 11:59:53 【问题描述】:

在一门关于多重继承的课程中,我遇到了这段漂亮的代码。

class First(object):
    def __init__(self):
        super(First, self).__init__()
        print("first")

class Second(object):
    def __init__(self):
        super(Second, self).__init__()
        print("second")

class Third(Second,First):
    def __init__(self):
        super(Third, self).__init__()
        print("third")

Third();

输出:

first
second
third

我有点害怕,所以我开始研究为什么这些东西还能奏效。我发现a lovely article about this matter 很好地解释了super 背后的机制。

然后我开始玩代码,我发现大部分代码实际上是多余的。我一步一步地修剪东西,直到只剩下这个可怜的骨架。

class First():
    def __init__(self):
        super().__init__()
        print("first")

class Second():
    def __init__(self):
        super().__init__()
        print("second")

class Third(Second,First):
    def __init__(self):
        super().__init__()
        print("third")

Third();

这会产生完全相同的输出。现在对于object,我知道这可以省略,因为所有类都派生自基类object。那里没有问题。但是我不太明白传递给super 方法的参数背后的内容。所以我做了最后的调整来检查这是否也能正常工作:

class First():
    def __init__(self):
        super().__init__()
        print("first")

class Second():
    def __init__(self):
        super().__init__()
        print("second")

class Third(Second,First):
    def __init__(self):
        super(self).__init__()
        print("third")

Third();

输出:

TypeError: super() argument 1 must be type, not Third

我可以理解self 在这种情况下指的是Third。在super(Third,self) 的情况下,Third 指的是一个类,它足以作为我认为的类型。那么在调用super 方法时,总是隐含所有这些冗余部分是否正确?除了我已经找到的链接之外,还有人有关于这些机制的一些很酷的文档吗?似乎它们被调用的顺序与列出类参数的顺序相反。 反转为class Third(First,Second) 给出输出:

second
first
third

我们将不胜感激。

【问题讨论】:

super with arguments 是 python 2 的原始形式,新的无参数形式来自 python 3:python.org/dev/peps/pep-3135 这实际上是编译器的特殊情况。虽然它只是语法糖 顺便说一句,即使是括号在类定义上也是多余的:class First:。分号也是如此。 【参考方案1】:

上面的例子代表了super 的第一个实现。该实现在以后的版本中变得更加智能,因此您应该使用第二个示例。另一个只是过时了。如果您使用多重继承,您可以将正确的父类传递给super,但这是一种特殊情况。

【讨论】:

【参考方案2】:

super 被创建时,在 Python 2.x 时代,它的参数(你想要“超级”的类,以及你调用方法的实例)需要是明确的。

从语言的角度来看,super 是一个普通的调用,没有特殊处理。

在创建 Python 3 时,人们一致认为想要调用超类中的方法很常见,因此值得特殊的语言处理,所以它是: 在 Python 3 中,调用 super 变得足够特殊,以至于它由编译器本身处理(而不是语言运行时 - 编译器,尽管以透明的方式运行,但与实际运行程序完全分开)。编译器安排创建一个隐藏的局部变量——它被称为__class__,而无参数的super() 调用实际上是super(__class__, self)__class__ 指向在外部 class 语句体中定义的类。这种机制实际上是发生在其他超显式 Python 中的“幕后发生的神奇事情”之一。

super() 的旧的、显式的形式,加上参数,当然仍然有效。

发现这些“不可见”机制的一个好方法是尝试将无参数的super 调用放在普通函数中,而不是方法中:尝试运行代码时会看到早期错误。

【讨论】:

以上是关于python中超级方法的隐含参数的主要内容,如果未能解决你的问题,请参考以下文章

python(面试题二)

一文详解python的类方法,普通方法和静态方法

js的隐含参数(arguments,callee,caller)使用方法

JS构造函数原型对象隐含参数this

python基础学习日志day6-类的方法

关于 Scala 隐含多个类型参数的问题