2017-06-12 10 views
0

をGETATTR、私は次のクラスを持っている:私は問題がこの質問を解決していデコレータの周りの作業と

class test: 

    @auth 
    def method1(self, x): 
     return x 

    @auth 
    def method2(self, x, y): 
     return x+y 

    def method3(self, z): 
     return z 

は、私は、次の両方の方法でデコレータを適用されません:

class auth: 

    def __init__(self, f): 
     self.f = f 

    def __call__(self, *args, **kwargs): 
     self.f(*args, **kwargs) 

これまでのところ何の問題を、しかし、私は、次のコードを使用する(必要性を)必要があります。

def run(): 
    klass = globals()["test"]() 

    method1 = getattr(klass, "method1") 
    print(method1.__code__.co_varnames) 
    # should print (self, x) 

    method2 = getattr(klass, "method2") 
    print(method2.__code__.co_varnames) 
    # should print (self, x, y) 

    method3 = getattr(klass, "method3") 
    print(method3.__code__.co_varnames) 
    # i get (self, z) < without decorator 

をしかし、私は今取得:

AttributeError: 'auth' object has no attribute '__code__' 

メソッド "method1 and method2"のシグネチャが "auth"になったと思われる場合はどうなりますか。

どのようにしてデコレータの有無にかかわらず引数を取得できますか。 私は "inspect"について読んで始めましたが、遅いことに関する報告がたくさんあります。

+0

'method1.f .__ code __。co_varnames'のようなものを使うことができます。しかし、一般に、あなたが使用する必要があるコードは、デコレータコードを認識している/協調している必要があります(つまり、関数の引数を見つけるためにどこを調べる必要があるか)。 – BrenBarn

答えて

1

authオブジェクトのf属性に「元の」メソッドが格納されています。代わりにmethod1.__code__.co_varnames使用のmethod1.f.__code__.co_varnames

+0

あなたは仲がいい!メソッドにデコレータがあるかどうかを知ることは可能ですか? (ほんの少しの質問) – Jonny

+0

私はわかりませんが、[this](https://stackoverflow.com/questions/19314405/how-to-detect-is-decorator-has-been-applied-to-method-または関数)はどこかで始まるかもしれません –

+0

ありがとう、私は__code__を使用することができます!=代わりに、リンクのようにinspect.getargspecが、とにかく感謝マン。 – Jonny

1

注釈はちょうどそれがクラスauthなくfunctionの対象である、オブジェクトが含まれているとitsself対象ではありません。関数自体にアクセスするには、のauth-objectに関数の__dict__オブジェクトのコピーを割り当てるか、methodN.f.__code__.co_varnamesと書くことができます。

class auth: 

    def __init__(self, f): 
     self.__dict__.update(f.__dict__) 
     # now the initialisations 
     self.f = f 

    def __call__(self, *args, **kwargs): 
     self.f(*args, **kwargs) 

編集: あなたはfは、例えば、更新によって上書きされる可能性があるため、辞書を更新した後、スーパーを呼び出す/メンバーを初期化する必要があります。別のデコレータクラスを定義し、メンバはfです。

+0

ありがとうございます、それは解決され、dictのアップデートで素晴らしい回避策です – Jonny

関連する問題