理解Python中的super

2024-04-28 04:26:10 发布

您现在位置:Python中文网/ 问答频道 /正文

你能给我解释一下如何用Python编写致命的钻石吗?我看到了许多没有使用构造函数参数的类似代码示例,但一旦我开始使用参数,事情就开始变得一团糟

class A:
    def __init__(self, a):
        self.a = a

class B(A):
    def __init__(self, a, b):
        self.b = b
        super().__init__(a)

class C(A):
    def __init__(self, a, c):
        self.c = c
        super().__init__(a)

class D(B, C):
    def __init__(self, a, b, c, d):
        self.d = d
        # How do I pass a and b to B.__init__
        # and a and c to C.__init__
        # using super() ?
        super().__init__(a, b, c) #???

d = D(1, 2, 3, 4)

Tags: andto代码self示例参数initdef
2条回答

您的子类初始值设定项没有兼容的签名,这是正确协作超级调用的关键

这里的简单解决方案是通过在整个链中添加对varargs和任意关键字args的支持,使这些签名在规范上兼容,即:

# NB: Python3 required, won't work in Py2

class A:
    def __init__(self, a, *args, **kwargs):
        self.a = a

class B(A):
    def __init__(self, a, b, *args, **kwargs):
        super().__init__(a, *args, **kwargs)
        self.b = b

class C(A):
    def __init__(self, a, c, *args, **kwargs):
        super().__init__(a, *args, **kwargs)
        self.c = c

class D(B, C):
    def __init__(self, a, b, c, d, *args, **kwargs):
        super().__init__(a, b=b, c=c, *args, **kwargs)
        self.d = d


d = D(1, 2, 3, 4)

当然,这并不能解决多重继承和协作super调用的每一个可能问题,但是MI很棘手,而且对可能发生的事情也有限制

最简单的方法可能是每个子类接受kwargs的dict,并将其传递给上层:

class A:
    def __init__(self, a):
        self.a = a

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

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

class D(B, C):
    def __init__(self, d, **kwargs):
        self.d = d
        super().__init__(**kwargs)

d = D(a=1, b=2, c=3, d=4)

print(d.a, d.b, d.c, d.d)
# 1 2 3 4

在每次调用中,__init__获取所需的参数,并将其余参数传递给父类。唯一的缺点是必须将参数作为关键字传递

相关问题 更多 >