対象のクラスのメソッド呼び出し前に割り込む【Python】

Feb. 25, 2023, 5:28 p.m.

#Python 

あるクラスのメソッドを呼び出す前に割り込んで何かの処理をしたい場合がある。普通はそのクラスを継承し同名メソッドを作ればよいが、数がたくさんあるなど面倒なケースもある。そうしたときに使える方法。

例えば、以下のような対象のクラス Target の各メソッド(A, B)呼び出し前に処理を割り込ませる場合を考える。

class Target:
    def __init__(self, a):
        self.a = a

    def A(self):
        return self.a

    def B(self, num):
        self.a += num

そのために Hook クラスを用意し、こちらを Target クラスの代わりに用いる。今回は割り込む処理として、単純に呼ばれたメソッド名を出力するものを考える。

class Hook:
    def __init__(self, target):
        self.target = target

    def __getattr__(self, name):
        print(f'name: {name}')
        return self.target.__getattribute__(name)

そして実際に使ってみると

hook = Hook(Target(5))
print(hook.A())
hook.B(3)
print(hook.A())

より、

name: A
5
name: B
name: A
8

と得られる。ここで __getattr__ を利用している。これは Hook の保持していない属性にアクセスした場合に呼ばれる特殊メソッドで、今回のケースに有用なものとなっている(ドキュメント

この方法は、例えばあるクラスの各メソッドが何回呼ばれているかを計測することなどに使えると思う(というか、そのために作った)。以上