我正在尝试正确获取__init__
执行的顺序。层次结构由两个分支组成。左分支实现了右分支的一些抽象方法。在右分支中,也有一个拆分。现在,我希望他们执行:左上到底部,然后向下右上到底。
有没有办法在Python 3中实现这一目标?
因此,基本上以下应按顺序打印数字(没有):
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)(L1)和L2(L1A,L2A)。那是完全分开一些功能。
怎么样:
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
['X', 'L2', 'L1', 'R2a', 'R1', 'object']
我认为您不能更改MRO,['X', 'L2', 'L1', 'R2a', 'R1', 'object']
。但是您可以选择在super().__init__()
之前或之后放置初始化语句。
将打印语句放在super().__init__()
之前,以MRO的顺序为您提供打印语句。之后将它们放置,倒转订单。
您希望订单部分逆转:l2之前的L1,R2之前的R1。
当我们到达L1时,通过调用self.init()
,我们可以在MRO链的开头开始,并以所需的顺序致电init
:L1, L2
。
我更喜欢避免使用超级:
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()
此打印:
init A
init B
init C
因此,对于您的具体情况,只需致电_ init _ in无论您想要什么顺序。真的。去尝试一下。钻石或没有钻石,它可以很好地工作。
eg:
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