在Python中强制执行具有多重继承的特定于\uyu init_uu

2024-05-03 10:30:34 发布

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

我正在尝试使__init__的执行顺序正确。层次结构由两个分支组成。左分支实现了右分支的一些抽象方法。在右边的树枝上也有一个裂缝。现在我希望他们执行:先左上下,然后右上下。

在Python3中有没有实现这一点的方法?

因此,基本上,下面应该按顺序打印数字(事实并非如此):

from abc import abstractmethod, ABCMeta

class L1:
    def __init__(self):
        super().__init__()
        print(1)

class R1(metaclass=ABCMeta):
    def __init__(self):
        super().__init__()
        print(3)

    @abstractmethod
    def m(self):
        pass

class L2(L1):
    def __init__(self):
        super().__init__()
        print(2)

    def m(self):
        pass

class R2a(R1):
    def __init__(self):
        super().__init__()
        print(4)

class R2b(R1):
    def __init__(self):
        super().__init__()
        print(4)

class X(L2, R2a):
    pass

class Y(L2, R2b):
    pass

x = X()
print("--")
y = Y()

不幸的是,我不能改变L2和R2的顺序,因为L2实现了R2的抽象方法(如果我改变了它,就会出现错误)。

有可能吗?

(你知道一个很好的方法来思考MRO,以轻松解决此类问题吗?)

编辑:我想我没关系,但我想指出的是,在我的真实结构中,实际上在L侧有一个钻石,像L2a(L1)、L2b(L1)和L2(L1a,L2a)。这是为了完全分离一些功能。


Tags: 方法selfl1顺序initdef分支pass
2条回答

我宁愿避免使用超级:

class A:
    def __init__(self):
        print('init A')

class B:
    def __init__(self):
        print('init B')

class C(B,A):
    def __init__(self):
        A.__init__(self)
        B.__init__(self)
        print('init C')

c = C()

打印:

^{pr2}$

因此,对于您的具体情况,只要按您想要的顺序调用init。真正地。试试吧。钻石或没有钻石都会很好的。在

例如:

class X(L2,R2a):
    def __init__(self):
        L1.__init__(self)
        L2.__init__(self)
        R1.__init__(self)
        R2a.__init__(self)

如果你需要调用init来获取层次结构中更高层次的东西,并且你害怕为某些对象重复调用某些类的init函数,那么只需创建一些布尔标志。在

例如:

class L1:
    def __init__(self):
        try:
            if self.l1_initialised:
                return
        except NameError:
            self.l1_initialised = True
        blah blah blah

怎么样:

from abc import abstractmethod, ABCMeta

class L1:
    def __init__(self):
        self.init()
        super().__init__()
    def init(self):
        print(1)

class R1(metaclass=ABCMeta):
    def __init__(self):
        print(3)
        super().__init__()

    @abstractmethod
    def m(self):
        pass

class L2(L1):
    def __init__(self):
        super().__init__()
    def init(self):
        super().init()
        print(2)

    def m(self):
        pass

class R2a(R1):
    def __init__(self):
        super().__init__()
        print(4)


class R2b(R1):
    def __init__(self):
        super().__init__()
        print(4)

class X(L2, R2a):
    pass

class Y(L2, R2b):
    pass

x = X()
print([cls.__name__ for cls in X.mro()])

它产生了

^{pr2}$

我认为你不能改变MRO,['X', 'L2', 'L1', 'R2a', 'R1', 'object']。但是您可以选择将初始化语句放在super().__init__()之前或之后。在

将print语句放在super().__init__()之前,将按照MRO的顺序给出print语句。之后再放,顺序颠倒。在

你想要部分颠倒顺序:L1在L2之前,R1在R2a之前

当我们到达L1时,通过调用self.init(),我们可以从MRO链的开始重新开始,并按所需的顺序调用initL1, L2。在

相关问题 更多 >