4

私は__init__実行の順序を正しくしようとしています。階層は 2 つのブランチで構成されます。左のブランチは、右のブランチのいくつかの抽象メソッドを実装しています。右枝にも分岐があります。今、私はそれらを実行したいと思います: 最初に上から下に左、次に右に上から下。

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 について考える良い方法を知っていますか?)

編集: 私は問題ではないと思っていましたが、私の実際の構造では、L2a(L1)、L2b(L1)、L2(L1a、L2a) のように L 側にダイヤモンドがあることに注意してください。これは、いくつかの機能を完全に分割することです。

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__()

前にprintステートメントを配置super().__init__()すると、MROの順序でprintステートメントが表示されます。後で配置すると、順序が逆になります。

順序を部分的に逆にする必要があります。L1はL2の前、R1はR2aの前です。

L1に到達するとself.init()、を呼び出すことにより、MROチェーンの最初からやり直しinit、目的の順序で呼び出しますL1, L2

于 2012-11-09T13:13:01.713 に答える