Skip to content Skip to sidebar Skip to footer

Second Parameter Of Super()?

A colleague of mine wrote code analogous to the following today, asked me to have a look, and it took me a while to spot the mistake: class A():

Solution 1:

The only thing that causes all these ambiguities is that "why obj = super(B).__init__() works?". That's because super(B).__self_class__ returns None and in that case you're calling the None objects' __init__ like following which returns None:

In [40]: None.__init__()

Regarding the rest of the cases, you can simply check the difference by calling the super's essential attributes in both cases:

In [36]: classB(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]: classB(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'>
NoneNone

For the rest of the things I recommend you to read the documentation thoroughly. 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/.

Moreover, If you want to know why super(B) doesn't work outside of the class and generally why calling the super() without any argument works inside a class you can read This comprehensive answer by Martijn https://stackoverflow.com/a/19609168/2867928.

A short description of the solution:

As mentioned in the comments by @Nathan Vērzemnieks you need to call the initializer once to get the super() object work. The reason is laid behind the magic of new super object that is explained in aforementioned links.

In [1]: classA:
   ...:     def__init__(self):
   ...:         print("finally!")
   ...:

In [2]: classB(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!

Solution 2:

The confusion here comes from the fact that (in a class definition context) super() gives a bound super object which then delegates __init__ to its __self_class__, while super(B) creates an unbound super object which, because its __self_class__ is None, does not delegate.

In [41]: classTest(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 superobject at 0x10835c3c8>

So when you call super(B).__init__(), it creates an unbound super but then immediately calls __init__ on it; that, because of the magic described in the various links in this other answer, binds that unbound super. There are no references to it, so it disappears, but that's what's happening under the hood.

Post a Comment for "Second Parameter Of Super()?"