Home > database >  Why does super()() not do the same as super().__init__()?
Why does super()() not do the same as super().__init__()?

Time:06-23

I have been wondering this for a while now, and I hope this isn't a stupid question with an obvious answer I'm not realizing: Why can't I just call the __init__ method of super() like super()()? I have to call the method like this instead: super().__init__()

Here is an example that gets a TypeError: 'super' object is not callable error when I run it (specifically on line 6 that comes from line 3 in __init__):

class My_Int(int):
    def __init__(self,value,extr_data=None):
        super()(value)
        self.extr_data=extr_data

x=My_Int(3)

Doesn't super() get the inherited class int making super()(value) the same as int(value)?

Furthermore, why can't I use the len function with super() when inheriting from the class list? Doesn't len() do the same as __len__()?

class My_List(list):
    def some_method1(self):
        print(len(super()))

    def some_method2(self):
        print(super().__len__())

x=My_List((1,2,3,4))

x.some_method2()
x.some_method1()

This example prints 4 and then an error as expected. Here is the output exactly:

4
Traceback (most recent call last):
  File "/home/user/test.py", line 11, in <module>
    x.some_method1()
  File "/home/user/test.py", line 3, in some_method1
    print(len(super()))
TypeError: object of type 'super' has no len()

Notice I called some_method2 before calling some_method1 (sorry for the confusion).

Am I missing something obvious here?

  • P.S. Thanks for all the help!

CodePudding user response:

super() objects can't intercept most special method calls, because they bypass the instance and look up the method on the type directly, and they don't want to implement all the special methods when many of them won't apply for any given usage. This case gets weirder, super()() would try to lookup a __call__ method on the super type itself, and pass it the super instance.

They don't do this because it's ambiguous, and not particularly explicit. Does super()() mean invoke the super class's __init__? Its __call__? What if we're in a __new__ method, do you invoke __new__, __init__ or both? Does this mean all super uses must implicitly know which method they're called in (even more magical than knowing the class they were defined in and the self passed when constructed with zero arguments)?

Rather than deal with all this, and to avoid implementing all the special methods on super just so it can delegate them if they exist on the instance in question, they required you to explicitly specify the special method you intend to call.

  • Related