使用具有多重继承的 super()

Using super() with multiple inheritance

代码是不言自明的。我想同时调用 class A 和 class 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()

为了这个目的,我在我的 public 库中制作了一个 metaclass。设置第一个碱基的metaclassclass.

它使任何继承者自动调用它的基 __init__,而不必担心 super() 调用,从而使您可以编写更清晰的代码。它也很宽容,因为它将缺少的参数设置为 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

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

然后由于 Cself.nameself.age 的定义推迟到父 classes,您立即使用 super().__init__(**kwargs) 将所有参数向上传递到层次结构.关于继承的最好的事情是子 classes 甚至不需要知道它不处理的参数。第一个父 class 是 A,所以 self.name 在那里定义。方法解析顺序中的下一个父 class 是 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

一个简单的解决方案是在所有初始化器中使用 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 隔离开来,您可以确保在点击 object 之前消耗掉所有 kwargs