Python多继承:如何调用两个父类的__init__方法?
多继承场景下的父类__init__调用问题
你想要实现多继承,让子类Flat同时继承Place和Product,并在子类的__init__中调用两个父类的初始化方法,但当前代码触发了TypeError: super() argument 1 must be type, not str错误,问题出在super()的用法上。
错误原因分析
你写的super(Place).__init__(country, city, **attr)是错误的用法:
- 在Python3中,
super()如果带参数,正确格式是super(当前类, self).__init__(...),比如super(Flat, self).__init__(...),它会根据当前类的MRO(方法解析顺序)调用下一个类的方法。 - 你试图用
super(Place)直接指定调用Place的__init__,这不符合super的设计逻辑——super的第一个参数必须是当前子类的类型,而非要调用的父类。
解决方案
方案1:直接调用父类的__init__方法(更直观,推荐此场景)
在多继承且父类未设计为协作式继承的情况下,直接显式调用父类的__init__并传入self是最稳妥的方式,代码清晰不易出错:
class Place: def __init__(self, country, city, **attr): self.country = country self.city = city self.attributes = attr def show_location(self): print(self.country, self.city) class Product: def __init__(self, price, currency = '$'): self.price = price self.currency = currency def show_price(self): print(self.price, self.currency) class Flat(Place, Product): def __init__(self, country, city, street, number, price, currency = '$', **attr): # 直接调用Place的__init__,传入self和所需参数 Place.__init__(self, country, city, **attr) # 直接调用Product的__init__,传入self和所需参数 Product.__init__(self, price, currency) self.street = street self.number = number def show_address(self): print(self.number, self.street) myflat = Flat('Mozambique', 'Nampula', 'Rua dos Combatentes', 4, 150000, '$') # 测试方法 myflat.show_location() # 输出 Mozambique Nampula myflat.show_price() # 输出 150000 $ myflat.show_address() # 输出 4 Rua dos Combatentes
方案2:使用super()实现协作式多继承(需调整父类代码)
如果要使用super(),需要让所有父类遵循协作式继承规范——在自己的__init__中调用super().__init__(),并通过**kwargs传递剩余参数,这样子类可通过一次super()调用触发MRO链上所有父类的初始化:
class Place: def __init__(self, country, city, **attr): self.country = country self.city = city self.attributes = attr # 调用MRO链下一个类的__init__ super().__init__(**attr) def show_location(self): print(self.country, self.city) class Product: def __init__(self, price, currency = '$', **kwargs): self.price = price self.currency = currency # 调用MRO链下一个类的__init__ super().__init__(**kwargs) def show_price(self): print(self.price, self.currency) class Flat(Place, Product): def __init__(self, country, city, street, number, price, currency = '$', **attr): # 调用MRO链第一个父类的__init__,参数通过super链式传递 super().__init__(country=country, city=city, price=price, currency=currency, **attr) self.street = street self.number = number def show_address(self): print(self.number, self.street) myflat = Flat('Mozambique', 'Nampula', 'Rua dos Combatentes', 4, 150000, '$')
这种方式的优势是子类代码更简洁,但要求所有父类都设计为支持协作式继承,适合父类属于同一继承体系的场景。
两种方式的对比
- 直接调用父类__init__:无需修改父类代码,逻辑直观,适合父类独立、无协作设计的多继承场景,是你当前案例的最优选择。
- 使用super():需要父类配合调整,适合构建协作式继承体系,能避免重复调用和MRO相关潜在问题,但对父类设计有要求。
内容的提问来源于stack exchange,提问作者Arkeor
相关产品推荐
相关产品推荐

