2016-12-08 8 views
0
import time 
class Timeit(object): 
    def __init__(self, func): 
     self._wrapped = func 
    def __call__(self, *args, **kws): 
     start_time = time.time() 
     result = self._wrapped(*args, **kws) 
     print("elapsed time is %s " % (time.time() - start_time)) 
     return result 

このようなクラスデコレータを作成しますが、インスタンスメソッドに使用すると動作しません。pythonクラスデコレータが動作しません

class A(object): 
    @Timeit 
    def func(self): 
     time.sleep(1) 
     return 'invoking method func' 
if __name__ == '__main__': 
    a = A() 
    a.func() # Boom! 

私は誰に説明できますか?通常の方法でうまく動作します。

+0

デコレータとして使用されているだけのクラスのクラスデコレータ、ないことを。 –

+0

これをチェックしてください。 http://stackoverflow.com/questions/9416947/python-class-based-decorator-with-parameters-that-c​​an-decorate-a-method-or-a-fun – Prajwal

+0

自分でデコレータを作成してみてください。関数またはインスタンスメソッドの両方で正しく動作するように、すべての面倒な作業を行うパッケージを使用し、正しく実行します。ラップを見てみましょう。 http://wrapt.readthedocs.io –

答えて

0

あなたの@Timeitデコレータは、A.funcが機能ではなくオブジェクトであることを意味します。したがって、あなたが評価する際:

a.func() 

を暗黙のself引数でバインド方法機能をオンクラスメソッドの特別なPythonの処理は有効になりません。あなたが実行した場合:

a.func(a) 

が欠落引数を供給し、それが正常に動作しますが、明らかにそれはあなたが望むものではありません。

ラッパーがオブジェクトではなく関数を返すようにする必要があります。最も簡単な方法は、クラスとしてTimeitを実装放棄してあなたのコードを置き換えることです:

import time 
from functools import wraps 

def Timeit(f): 
    @wraps(f) 
    def wrapper(*args, **kwds): 
     start_time = time.time() 
     result = f(*args, **kwds) 
     print("elapsed time is %s " % (time.time() - start_time)) 
     return result 
    return wrapper 

class A(object): 
    @Timeit 
    def func(self): 
     time.sleep(1) 
     return 'invoking method func' 

if __name__ == '__main__': 
    a = A() 
    a.func() # works fine now 
+0

thx a lot!@K。 A. Buhr – yunji

+0

あなたは彼の答えを受け入れるべきです –

関連する問題