class Car:
def __init__(self, door, wheel):
self.door = door
self.wheel = wheel
def start(self):
print('Start the Car')
def go(self):
print('Going')
class Flyable:
def __init__(self, wing):
self.wing = wing
def start(self):
print('Start the Flyable object')
def fly(self):
print('Flying')
class FlyingCar(Flyable, Car):
def __init__(self, door, wheel, wing):
super().__init__(wing=wing)
self.door = door
self.wheel = wheel
def start(self):
super().start()
if __name__ == '__main__':
car = FlyingCar()
car.start()
print(FlyingCar.__mro__)
It was expected to
instantiate FlyingCar(), and call the start() method. This should have returned ‘Start the Flyable object’ as the mro has Flyable as the first inheritance.
display the mro of the start() call.
Instead, I get:
"
car = FlyingCar()
TypeError: FlyingCar.init() missing 3 required positional arguments: ‘door’, ‘wheel’, and ‘wing’
"
So, I am confused. It seems like the tutorial has erred in the syntax of the init of FlyingCar()
I have tried poking around with various ordering, and such but have had no luck. Something is wrong with this code, but I don’t know what.
More importantly, I don’t have a strategy beyond posting for help to sort it out. I do not yet ‘think in Python’. Not even sure where I would go in the docs to start a logical bug hunt. Any suggestions on a general flowchart for how to take an error message and backtrack to an issue would be most appreciated!
you have this init method which takes 3 additional parameters def __init__(self, door, wheel, wing):
but you do not provide one of them: car = FlyingCar()
you might change to something like: car = FlyingCar(2, 3, 1)
which is equivalent to car = FlyingCar(door=2, wheel=3, wing=1)
See Python’s super() considered super! | Deep Thoughts by Raymond Hettinger. In short, all classes in the hierarchy need to use super, not just your subclass. It’s also recommended to use keyword arguments to simplify hiding arguments unneeded by one class while still ensuring they get passed to where they are needed. And finally, you need to actually provide arguments when instantiating FlyingCar.
class Car:
def __init__(self, *, door, wheel, **kwargs):
super().__init__(**kwargs)
self.door = door
self.wheel = wheel
def start(self):
print('Start the Car')
def go(self):
print('Going')
class Flyable:
def __init__(self, *, wing, **kwargs):
super().__init__(**kwargs)
self.wing = wing
def start(self):
print('Start the Flyable object')
def fly(self):
print('Flying')
class FlyingCar(Flyable, Car):
pass
if __name__ == '__main__':
car = FlyingCar(wing=1, wheel=2, door=3)
car.start()
When you call FlyingCar, it invokes the inherited Flying.__init__ (since Flying is the first subclass), which calls Car.__init__, which will call object.__init__, which does little more than stop the chain of calls to __init__ methods.
The linked tutorial doesn’t seem to understand how super works, or how to use it properly.
Your expectations are correct: calling car = FlyingCar() will call FlyingCar’s __init__() method, which in turn calls Flyable’s __init__() method.
However, you don’t pass three arguments for the door, wheel, and wing parameters that FlyingCar’s __init__() method requires. That’s why you’re getting the error message.
Thanks everyone! That solved it. I need to dive deeper into super() to see what is actually happening here. I get that the argument # of each class need to be the same if you are calling up and down the family tree. Wasn’t aware of the placeholder ‘*’ and ✱kwrds very cool.