Python中为何MRO末位类的super().__init__需无参?否则会抛运行时异常
super().__init__ call? Great question! Let's break this down with your code example and how Python's Method Resolution Order (MRO) and super() actually work.
First, recap how super() and MRO interact
Contrary to what many beginners assume, super() doesn't just call the "parent class" method. Instead, it looks up the next method in the MRO chain of the current instance.
For your class hierarchy:
class A(object): def __init__(self, **args): print('A.__init__') self.a = args['a'] super(A, self).__init__(**args) class B (object): def __init__(self, **args): print('B.__init__') self.b = args['b'] # super(B, self).__init__(**args) class C(A, B): def __init__(self, **args): print('C.__init__') self.c = args['c'] super(C, self).__init__(**args)
The MRO for an instance of C is: C → A → B → object. This is the fixed order Python uses to resolve method calls for that instance.
What happens when you call super().__init__ in the last custom class?
Let's trace the execution step by step when you create a C instance:
C.__init__runs, callssuper(C, self).__init__(**args)→ this finds the next class in MRO afterC(which isA), soA.__init__executes.A.__init__runs, callssuper(A, self).__init__(**args)→ next in MRO afterAisB, soB.__init__executes.B.__init__runs. If you uncomment thesuper(B, self).__init__(**args)line, Python will look for the next class in MRO afterB—which isobject.
Here's the critical detail: object.__init__ only accepts one argument: self. It has no logic to handle extra positional or keyword parameters. If you pass **args to it (like in the uncommented line), Python will throw a runtime error because you're sending parameters that object.__init__ doesn't expect.
Why does this only affect the "last" class in the MRO?
The "last" custom class in the MRO is the one immediately preceding object. Any class before that in the chain will have another custom class (not object) as the next entry in the MRO, so passing parameters to super().__init__ is safe—as long as those next classes accept those parameters (like how A passes args to B, which is designed to handle **args).
Only when you reach the class right before object in the MRO, calling super().__init__ with parameters will send those parameters to object.__init__, which can't process them.
A quick fix example
If you want to keep the super() call in B, just avoid passing extra parameters to object.__init__:
class B(object): def __init__(self, **args): print('B.__init__') self.b = args['b'] super(B, self).__init__() # No extra args passed to object.__init__
内容的提问来源于stack exchange,提问作者David

