4

我试图让__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) 和 L2(L1a、L2a)。那就是完全拆分一些功能。

4

2 回答 2

3

怎么样:

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

于 2012-11-09T13:13:01.713 回答
1

我更喜欢避免使用超级:

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
于 2012-11-09T12:07:46.240 回答