【问题标题】:Using super() with multiple inheritance使用具有多重继承的 super()
【发布时间】:2022-01-20 22:26:57
【问题描述】:

代码是不言自明的。我想同时调用A 类和B__init__ 方法。

代码:

class A(object):
    def __init__(self, name):
        self.name = name

class B(object):
    def __init__(self, age):
        self.age = age

class C(A, B):
    def __init__(self, name, age):
        A.__init__(self, name)
        B.__init__(self, age)


    def display(self):
        print(self.name, self.age)

c = C("xyz", 12)
c.display()

输出:

xyz 12

我想使用super() 而不是明确声明

A.__init__(self, name)
B.__init__(self, age)

我找不到相同的资源,需要帮助。

以下不起作用:

class A(object):
    def __init__(self, name):
        super(A, self).__init__()
        self.name = name

class B(object):
    def __init__(self, age):
        super(B, self).__init__()
        self.age = age

class C(A, B):
    def __init__(self, name, age):
        # A.__init__(self, name)
        # B.__init__(self, age)
        super(C, self).__init__(name, age)

    def display(self):
        print(self.name, self.age)

c = C("xyz", 12)
c.display()

【问题讨论】:

  • 不,我尝试了一些解决方案,但都没有效果
  • 你确定吗? super(A, self).__init__(name) 有效吗?
  • 如果两个超类没有兼容的__init__签名,你不能只用一个super调用。你正在做的事情已经做得很好了。
  • @NguyenThaiBinh 不,没有,你可以再次看到问题,我已经编辑了我的问题

标签: python oop inheritance super


【解决方案1】:

当您创建C 的实例时,最好传递关键字参数以便知道哪个是哪个。位置参数也可以,但是使用关键字参数,您不必担心会弄乱参数的顺序。

然后由于Cself.nameself.age 的定义推迟到父类,您立即使用super().__init__(**kwargs) 将所有参数传递到层次结构中。继承最好的一点是子类甚至不需要知道它不处理的参数。第一个父类是A,所以在那里定义了self.name。方法解析顺序中的下一个父类是B,因此从A,您将剩余的关键字参数传递给B,再次使用super().__init__(**kwargs)

class A(object):
    def __init__(self, name, **kwargs):
        self.name = name
        super().__init__(**kwargs)

class B(object):
    def __init__(self, age, **kwargs):
        self.age = age
        super().__init__(**kwargs)    # this is actually not needed but in case you have other base classes after B, might come in handy

class C(A,B):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def display(self):
        print(self.name, self.age)

c = C(name="xyz",age=12)
c.display()

输出:

xyz 12

【讨论】:

  • 我们的答案几乎相同。我必须给你一个 +1 我是真诚的 :)
【解决方案2】:

一个简单的解决方案是在所有初始化程序中使用kwargs,并传递您不关心的那些。

class A:
    def __init__(self, name, **kwargs):
        super().__init__(**kwargs)
        self.name = name

class B:
    def __init__(self, age, **kwargs):
        super().__init__(**kwargs)
        self.age = age

class C(A, B):
    def __init__(self, name, age, **kwargs):
        super().__init__(name=name, age=age, **kwargs)

    def display(self):
        print(self.name, self.age)

通过将您关心的参数与kwargs 隔离开来,您可以确保所有kwargs 在您点击object 之前都被消耗掉。

【讨论】:

  • 简洁明了。我实际上比我更喜欢你的回答:-)
【解决方案3】:

为此,我在我的公共图书馆中创建了一个元类。设置第一个基类的元类。

它使任何继承者自动调用其基础__init__s,而不必担心super() 调用允许您编写更简洁的代码。它也很宽容,因为它将缺少的 args 设置为 None

from generallibrary import AutoInitBases

class A(metaclass=AutoInitBases):
    def __init__(self,name):
        self.name=name

class B:
    def __init__(self,age):
        self.age=age

class C(A,B):
    def __init__(self,name,age):
        pass

    def display(self):
        print(self.name,self.age)

c=C("xyz",12)
c.display()
xyz 12

我不太关心向后兼容性,所以如果您安装它,请确保锁定版本。它支持python 3.8和3.9

pip install generallibrary==2.9.1

【讨论】:

  • 元类实际上是做什么的,为什么你认为它是一个很好的工具?
  • 更新了解释,我知道它有点过时了,但它确实让多重继承更容易使用
  • python 系统设计得非常好。我很确定引入一堆意想不到的行为不会让它变得更容易。话虽如此,否决票已删除。
猜你喜欢
  • 2014-07-01
  • 2021-11-28
  • 1970-01-01
  • 2017-07-30
  • 1970-01-01
  • 2016-02-25
  • 2020-07-24
  • 2018-12-08
  • 2020-03-20
相关资源
最近更新 更多