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.