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中超级方法的隐含参数的主要内容,如果未能解决你的问题,请参考以下文章