我正在努力争取执行__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)。这是为了完全分离一些功能。
您应该从object派生顶级类:class L1 (object):,以便获得"新样式类"。
@ber,不,他使用的是python 3(否则元类语法不起作用),所以他不必从object显式继承。
怎么样:
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的顺序给您打印对账单。之后再放,顺序颠倒。
您希望部分颠倒顺序:l1在l2之前,r1在r2a之前。
当我们到达l1时,通过调用self.init(),我们可以从MRO链的开始重新开始,并按所需的顺序调用init:L1, L2。
我更喜欢避免使用super:
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_即可。真正地。试试看。不管是钻石还是没有钻石,都会很好的。
如:
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
。
但问题是钻石结构,超类会被称为两次。实际上我没有提到我的二级课程也有分裂。
@Sheena:您应该使用super()使hte方法解析顺序(mro)算法工作。python.org/download/releases/2.3/mro版本
@贝尔:谢谢。正在调查…不过,我以前从来没有对这种做事方式有过问题。