Octpascal
@Octpascal

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Pythonのクラス継承で__init__に割り込みたい

Q&A

Closed

解決したいこと

次のようなクラスAがあり, __init__とその最後に呼ばれる post_init があります。

このクラスをクラスBに継承して, __init__post_initにそれぞれ処理を追加したいです。

class A:
    def __init__(self) -> None:
        print("A.init")
        self.post_init()

    def post_init(self):
        print("A.post_init")

class B(A):
    def __init__(self) -> None:
        super().__init__()
        print("B.init")

    def post_init(self):
        super().post_init()
        print("B.post_init")

この実装のとき

a = A()
# A.init
# A.post_init

b = B()
# A.init
# A.post_init
# B.post_init
# B.init

と出力されますが、

# A.init
# B.init
# A.post_init
# B.post_init

のようにそれぞれのタイミングで処理を追加したいです。

どのような実装方法がありますか?

0

2Answer

さらに継承されるとうまくいかないけど・・・

方法1
class A:
    def __init__(self) -> None:
        print("A.init")
        self.post_init()

    def post_init(self):
        print("A.post_init")

class B(A):
    def __init__(self) -> None:
        super().__init__()
        print("B.init")
        self.__my_post_init()

    def post_init(self):
        pass

    def __my_post_init(self):
        super().post_init()
        print("B.post_init")

a = A()
b = B()
方法2
class A:
    def __init__(self) -> None:
        print("A.init")
        self.post_init()

    def post_init(self):
        print("A.post_init")

class B(A):
    def __init__(self) -> None:
        post_init = self.post_init
        self.post_init = lambda: None
        super().__init__()
        print("B.init")
        self.post_init = post_init
        self.post_init()

    def post_init(self):
        super().post_init()
        print("B.post_init")

a = A()
b = B()
0Like

Comments

  1. @Octpascal

    Questioner

    ありがとうございます。
    実現できました!
    スマートな実装です

クローズ後に失礼します。
こういうのはいかがでしょうか?

class A:
    def __new__(cls, *args, **kwargs):
        instance = super().__new__(cls)
        instance.pre_init()
        return instance

    def __init__(self) -> None:
        print("A.init")
      
    def pre_init(self):
        print("A.pre_init")

class B(A):
    def __init__(self) -> None:
       super().__init__()
       print("B.init")
       
    def pre_init(self):
        super().pre_init()
        print("B.pre_init")
b = B()
# A.pre_init
# B.pre_init
# A.init
# B.init
0Like

Comments

  1. @Octpascal

    Questioner

    ありがとうございます。__new__を使う方法は思いつきませんでした👀

Your answer might help someone💌