super()的第二个参数?

时间:2018-01-17 13:18:53

标签: python python-3.x class super

我的一位同事今天写了类似下面的代码,让我看看,我花了一段时间才发现错误:

class A():                                                                                         
    def __init__(self):                                                         
        print('A')                                                              

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

b = B()

这里的问题是self的构造函数中super()没有B参数。让我感到惊讶的是,在这种情况下绝对没有任何事情发生,即没有错误,没有。 super创建的super(B)对象包含哪些内容?作为一个对象,它显然有一个构造函数,因此被调用的是什么,但该对象与B有何关系?特别是,为什么这个有效的代码并没有在某处抛出异常? super(B)是一个有实际用途的对象,会是什么?

2 个答案:

答案 0 :(得分:5)

导致所有这些含糊之处的唯一原因是“为什么obj = super(B).__init__()有效?”。那是因为super(B).__self_class__返回None,在这种情况下,您正在调用None对象'__init__,如下所示返回无:

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和Raymond Hettinger撰写的这篇文章https://rhettinger.wordpress.com/2011/05/26/super-considered-super/

此外,如果你想知道为什么super(B)在课堂外不起作用,一般为什么在课堂上调用super()没有任何参数可以阅读,你可以阅读Martijn的全面答案{ {3}}

解决方案的简短描述:

如@NathanVē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!

答案 1 :(得分:2)

这里的混淆来自于(在类定义上下文中)super()给出一个绑定的super对象,然后将__init__委托给它__self_class__,而{ {1}}创建一个未绑定的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;因为各种链接in this other answer中描述的魔法,绑定了未绑定的__init__。没有引用它,所以它消失了,但这就是幕后发生的事情。