super() 的第二个参数?
Second parameter of super()?
我的一个同事今天写了类似下面的代码,让我看一下,我花了一段时间才发现错误:
class A():
def __init__(self):
print('A')
class B(A):
def __init__(self):
super(B).__init__()
b = B()
这里的问题是 B
的构造函数中 super()
没有 self
参数。令我惊讶的是,在这种情况下绝对没有发生任何事情,即没有错误,什么也没有。 super(B)
创建的 super
对象包含什么?作为一个对象,它显然有一个构造函数,所以它就是被调用的,但是那个对象与 B
有什么关系?特别是,为什么这个有效代码没有在某处抛出异常? super(B)
是一个有实际用途的对象吗?
唯一导致所有这些歧义的是"why obj = super(B).__init__()
works?"。那是因为 super(B).__self_class__
returns None
并且在那种情况下你调用 None
对象的 __init__
就像下面的 returns None:
In [40]: None.__init__()
关于其余情况,您可以通过在这两种情况下调用 super
的基本属性来简单地检查差异:
In [36]: class B(A):
def __init__(self):
obj = super(B, self)
print(obj.__class__)
print(obj.__thisclass__)
print(obj.__self_class__)
print(obj.__self__)
....:
In [37]: b = B()
<class 'super'>
<class '__main__.B'>
<class '__main__.B'>
<__main__.B object at 0x7f15a813f940>
In [38]:
In [38]: class B(A):
def __init__(self):
obj = super(B)
print(obj.__class__)
print(obj.__thisclass__)
print(obj.__self_class__)
print(obj.__self__)
....:
In [39]: b = B()
<class 'super'>
<class '__main__.B'>
None
None
对于其余的事情,我建议您通读文档。 https://docs.python.org/3/library/functions.html#super and this article by Raymond Hettinger https://rhettinger.wordpress.com/2011/05/26/super-considered-super/.
此外,如果您想知道为什么 super(B)
在 class 之外不起作用,以及通常为什么不带任何参数调用 super()
在 class 内起作用] 你可以阅读 Martijn .
的综合回答
解决方案的简短描述:
正如@Nathan Vērzemnieks 在评论中提到的,您需要调用初始化程序一次才能使 super()
对象正常工作。原因在于上述链接中解释的新 super
对象的魔力。
In [1]: class A:
...: def __init__(self):
...: print("finally!")
...:
In [2]: class B(A):
...: def __init__(self):
...: sup = super(B)
...: print("Before: {}".format(sup))
...: sup.__init__()
...: print("After: {}".format(sup))
...: sup.__init__()
...:
In [3]: B()
Before: <super: <class 'B'>, NULL>
After: <super: <class 'B'>, <B object>>
finally!
这里的混淆来自这样一个事实:(在 class 定义上下文中)super()
给出一个绑定 super
对象,然后将 __init__
委托给它的 __self_class__
,而 super(B)
创建一个未绑定的 super
对象,因为它的 __self_class__
是 None
,所以 不是 委托。
In [41]: class Test(int):
...: def __init__(self):
...: print(super().__self_class__)
...: print(super().__init__)
...: print(super(Test).__self_class__)
...: print(super(Test).__init__)
...:
In [42]: Test()
<class '__main__.Test'>
<method-wrapper '__init__' of Test object at 0x10835c9c8>
None
<method-wrapper '__init__' of super object at 0x10835c3c8>
因此,当您调用 super(B).__init__()
时,它会创建一个未绑定的 super
,但随后会立即对其调用 __init__
;由于各种链接 中描述的魔法,绑定未绑定 super
。没有对它的引用,所以它消失了,但这就是引擎盖下发生的事情。
我的一个同事今天写了类似下面的代码,让我看一下,我花了一段时间才发现错误:
class A():
def __init__(self):
print('A')
class B(A):
def __init__(self):
super(B).__init__()
b = B()
这里的问题是 B
的构造函数中 super()
没有 self
参数。令我惊讶的是,在这种情况下绝对没有发生任何事情,即没有错误,什么也没有。 super(B)
创建的 super
对象包含什么?作为一个对象,它显然有一个构造函数,所以它就是被调用的,但是那个对象与 B
有什么关系?特别是,为什么这个有效代码没有在某处抛出异常? super(B)
是一个有实际用途的对象吗?
唯一导致所有这些歧义的是"why obj = super(B).__init__()
works?"。那是因为 super(B).__self_class__
returns None
并且在那种情况下你调用 None
对象的 __init__
就像下面的 returns None:
In [40]: None.__init__()
关于其余情况,您可以通过在这两种情况下调用 super
的基本属性来简单地检查差异:
In [36]: class B(A):
def __init__(self):
obj = super(B, self)
print(obj.__class__)
print(obj.__thisclass__)
print(obj.__self_class__)
print(obj.__self__)
....:
In [37]: b = B()
<class 'super'>
<class '__main__.B'>
<class '__main__.B'>
<__main__.B object at 0x7f15a813f940>
In [38]:
In [38]: class B(A):
def __init__(self):
obj = super(B)
print(obj.__class__)
print(obj.__thisclass__)
print(obj.__self_class__)
print(obj.__self__)
....:
In [39]: b = B()
<class 'super'>
<class '__main__.B'>
None
None
对于其余的事情,我建议您通读文档。 https://docs.python.org/3/library/functions.html#super and this article by Raymond Hettinger https://rhettinger.wordpress.com/2011/05/26/super-considered-super/.
此外,如果您想知道为什么 super(B)
在 class 之外不起作用,以及通常为什么不带任何参数调用 super()
在 class 内起作用] 你可以阅读 Martijn .
解决方案的简短描述:
正如@Nathan Vērzemnieks 在评论中提到的,您需要调用初始化程序一次才能使 super()
对象正常工作。原因在于上述链接中解释的新 super
对象的魔力。
In [1]: class A:
...: def __init__(self):
...: print("finally!")
...:
In [2]: class B(A):
...: def __init__(self):
...: sup = super(B)
...: print("Before: {}".format(sup))
...: sup.__init__()
...: print("After: {}".format(sup))
...: sup.__init__()
...:
In [3]: B()
Before: <super: <class 'B'>, NULL>
After: <super: <class 'B'>, <B object>>
finally!
这里的混淆来自这样一个事实:(在 class 定义上下文中)super()
给出一个绑定 super
对象,然后将 __init__
委托给它的 __self_class__
,而 super(B)
创建一个未绑定的 super
对象,因为它的 __self_class__
是 None
,所以 不是 委托。
In [41]: class Test(int):
...: def __init__(self):
...: print(super().__self_class__)
...: print(super().__init__)
...: print(super(Test).__self_class__)
...: print(super(Test).__init__)
...:
In [42]: Test()
<class '__main__.Test'>
<method-wrapper '__init__' of Test object at 0x10835c9c8>
None
<method-wrapper '__init__' of super object at 0x10835c3c8>
因此,当您调用 super(B).__init__()
时,它会创建一个未绑定的 super
,但随后会立即对其调用 __init__
;由于各种链接 super
。没有对它的引用,所以它消失了,但这就是引擎盖下发生的事情。