You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 13:31:07