1. ホーム
  2. python

[解決済み] インスタンスメソッドのデコレーターは、クラスにアクセスできますか?

2022-06-29 23:01:04

質問

おおよそ以下のような内容です。基本的には、インスタンスメソッドの定義で、インスタンスメソッドに使用されるデコレータから、インスタンスメソッドのクラスにアクセスする必要があります。

def decorator(view):
    # do something that requires view's class
    print view.im_class
    return view

class ModelA(object):
    @decorator
    def a_method(self):
        # do some stuff
        pass

そのままのコードでは

AttributeError: 'function' オブジェクトは 'im_class' という属性を持ちません。

似たような質問/回答がありました Pythonのデコレータは、関数がクラスに属していることを忘れさせます。 Pythonのデコレータでクラスを取得する - がありますが、これらは実行時に最初のパラメータを取得してインスタンスを取得するワークアラウンドに依存しています。 私の場合、私はそのクラスから得られた情報に基づいてメソッドを呼び出すので、呼び出しが来るのを待つことはできません。

どのように解決するのか?

Python 2.6以降を使用している場合、クラスデコレータを使用することができます。

def class_decorator(cls):
   for name, method in cls.__dict__.iteritems():
        if hasattr(method, "use_class"):
            # do something with the method and class
            print name, cls
   return cls

def method_decorator(view):
    # mark the method as something that requires view's class
    view.use_class = True
    return view

@class_decorator
class ModelA(object):
    @method_decorator
    def a_method(self):
        # do some stuff
        pass

メソッドデコレーターは "use_class" 属性を追加することでメソッドを注目すべきものとしてマークします - 関数とメソッドはオブジェクトでもあるので、追加のメタデータを付けることができます。

クラスが作成された後、クラスデコレーターはすべてのメソッドに目を通し、マークされたメソッドに対して必要なことを行います。

もしすべてのメソッドに影響を与えたいのであれば、 メソッド・デコレータを省略してクラス・デコレータを使用することができます。