Force specific __init__ execution with multiple inheritance in Python
我正在努力争取执行
在Python3中有实现这一点的方法吗?
所以基本上,下面应该按顺序打印数字(它没有):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 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)。这是为了完全分离一些功能。
怎么样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | 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()]) |
会产生
1 2 3 4 5 | 1 2 3 4 ['X', 'L2', 'L1', 'R2a', 'R1', 'object'] |
。
我认为你不能更改MRO,
把打印对账单放在
您希望部分颠倒顺序:l1在l2之前,r1在r2a之前。
当我们到达l1时,通过调用
我更喜欢避免使用super:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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() |
打印内容:
1 2 3 | init A init B init C |
号
因此,对于您的具体情况,只需按您想要的顺序调用_init_即可。真正地。试试看。不管是钻石还是没有钻石,都会很好的。
如:
1 2 3 4 5 6 | class X(L2,R2a): def __init__(self): L1.__init__(self) L2.__init__(self) R1.__init__(self) R2a.__init__(self) |
如果需要为层次结构中更高层的内容调用init,并且害怕为某些对象重复调用某些类的init函数,那么只需制作一些布尔标记。
例如:
1 2 3 4 5 6 7 8 | class L1: def __init__(self): try: if self.l1_initialised: return except NameError: self.l1_initialised = True blah blah blah |
。