Python“新风格”多重继承与多个_init__参数相结合

2024-06-23 18:51:49 发布

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

据我所知,如果所有类都使用“新样式”,则会发生以下情况:

class A(object):
    def __init__(self):
        print("Entering A")
        super().__init__()
        print("Leaving A")

class B(object):
    def __init__(self):
        print("Entering B")
        super().__init__()
        print("Leaving B")

class C(A, B):
    def __init__(self):
        print("Entering C")
        super().__init__()
        print("Leaving C")

c = C()
Entering C
Entering A
Entering B
Leaving B
Leaving A
Leaving C

在理解了super使用原始对象(c)的MRO之后,就可以理解为什么Entering/Leaving是这样的。但是,如果我需要将一些特定的参数传递给AB,但是在C中接收参数的顺序与AB不相似,该怎么办

class A(object):
    def __init__(self, x1, x2):
        print(f"Entering A [x1={x1}, x2={x2}]")
        super().__init__()
        print("Leaving A")

class B(object):
    def __init__(self, y1, y2):
        print(f"Entering B [y1={y1}, y2={y2}]")
        super().__init__()
        print("Leaving B")

class C(A, B):
    def __init__(self, x1, y1, x2, y2):
        print(f"Entering C [x1={x1}, y1={y1}, x2={x2}, y2={y2}]")
        super().__init__()
        print("Leaving C")

c = C('x1', 'y1', 'x2', 'y2')

我可以考虑整天到处转转,但我觉得可能有更好的方式

另外,如果B是库的一部分,因此我们无法更改它,并且它使用的是位置参数,而不是kwargs,该怎么办?在这种情况下,我能做什么,因为我认为手动处理MRO不是一个好主意,但同时B的构造函数不会接受kwargs

解决上述问题的正确方法是什么


Tags: selfobjectinitdef情况classprintx1
1条回答
网友
1楼 · 发布于 2024-06-23 18:51:49

好吧,这真的不再适合评论了,但这里似乎有一点误解

用于:

class C:
    def __init__(self, arg1=1):
        self.attr1 = arg1

class D(C):
    def __init__(self, arg1):
        super().__init__()

这将产生:

d = D(2)
print(d.attr1)  # prints: 1

因为通过super().__init__()我们调用了父级的构造函数,但我们没有传递任何参数,它以默认值运行

或者引用文档说明super的工作:

Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class.

也就是说,您“只”获得(可能绑定)要调用的解析方法。不多不少。它不会整理你传递的任何论点。因此,您的示例实际上不起作用,因为两个父构造函数都需要一个实例和两个以上的参数

在你的例子中,你可以说:

class A:
    def __init__(self, x1, x2):
        print(f"Entering A [x1={x1}, x2={x2}]")
        print("Leaving A")

class B:
    def __init__(self, y1, y2):
        print(f"Entering B [y1={y1}, y2={y2}]")
        print("Leaving B")

class C(A, B):
    def __init__(self, x1, y1, x2, y2):
        print(f"Entering C [x1={x1}, y1={y1}, x2={x2}, y2={y2}]")
        A.__init__(self, x1, x2)
        B.__init__(self, y1, y2)
        print("Leaving C")

因为您使用相应的特定参数调用每个特定的父构造函数。文档(same place,关于第二个具有多重继承的常见用例的下面几段)也包含关于以下内容的提示:

Good design dictates that this method have the same calling signature in every case (because the order of calls is determined at runtime, because that order adapts to changes in the class hierarchy, and because that order can include sibling classes that are unknown prior to runtime).

也就是说,你得到一个代理来调用这个方法。。。你用它的参数来称呼它。。。这必须是一个固定/稳定的集合,因为您无法事先确定通过该代理使用哪种方法

相关问题 更多 >

    热门问题