2016-06-13 9 views
1

のためのデコレータとして、私はいくつかの仕事を準備し、状況に機能を記録しなければならないのためにデコレータを使用したいので、私はそのような何か書く:クラスは、クラスメソッド

class Decorator: 
    def __init__(self, func): 
     self.count = 0 
     self.func = func 

    def __call__(self, *args, **kwargs): 
     self.count += 1 # Simply count the call times 
     return self.func(self, *args, **kwargs) 

class Foo: 
    def __init__(self): 
     self.value = 0 

    @Decorator 
    def test(self, value): 
     self.value = value # change the value of instance 
     print(self.value) 

f = Foo() 
f.test(1) 

print(f.value) 
print(f.test.value) 

をしかしself__call__(self, *args, **kwargs)で対応していること、それは明らかです例えばFooの代わりにDecoratorのインスタンスに変更すると、f.valueは変更されませんが、f.test.valueが増加します。

Decoratorの代わりにFooのインスタンスをDecoratorに渡す方法はありますか?

また、この関数を実装する方法ははるかに明確ですか?

ありがとうございました。

+0

ことができますか? –

+0

私はあなたの質問を完全に理解していないと私は200%確信しています。あなたのコードのように、@Decoratorを使ってメソッドを呼び出した回数を記録したいとします。それは問題ありませんが、後で**カウント**にアクセスする方法を教えてください。 ** Foo **のインスタンスを** Decorator **に渡すことができる例を試しましたが、f.test.valueは機能しません。 –

+0

'f.test.count'を使用してカウントにアクセスできます。' f 'は' Foo'のインスタンスです。 – Leon

答えて

3

デコレータは一度だけ呼び出され、すべてのインスタンスのメソッドをDecoratorクラスの1つのインスタンスに置き換えます。それがないすべては、次のとおりです。

Foo.test = Decorator(Foo.test) 

これは、それが不可能というインスタンスを検出することができます。 1つのワークアラウンド手でFoo__init__でデコレータを適用するには、次のようになります。

class Foo: 
    def __init__(self): 
     self.value = 0 
     self.test = Decorator(self.test) 

    def test(self, value): 
     self.value = value # change the value of instance 
     print(self.value) 

あなたが__call__Decoratorのでselfを渡す必要はありませんので、デコレータは、インスタンスメソッドをラップします。この方法:

class Decorator: 
    def __init__(self, func): 
     self.count = 0 
     self.func = func 

    def __call__(self, *args, **kwargs): 
     self.count += 1 # Simply count the call times 
     return self.func(*args, **kwargs) 

は、今では動作しf.test.valueがもう存在しないとして、あなたは、あなたの試験方法を更新する必要がありません:

f = Foo() 
f.test(1) 

print(f.value) 

期待どおりに1の2回出力します。

+0

upvote for simplicity :) –

0

私はこのhere

import functools 

class Decorator(object): 
    def __init__(self, func): 
     self.count = 0 
     self.func = func 


    def __call__(self, *args, **kwargs): 
     self.count += 1 # Simply count the call times 
     return self.func(*args, **kwargs) 

    def __get__(self, instance, instancetype): 
     """Implement the descriptor protocol to make decorating instance 
     method possible. 
     """ 

     # Return a partial function with the first argument is the instance 
     # of the class decorated. 
     return functools.partial(self.__call__, instance) 



class Foo: 
    def __init__(self): 
     self.value = 0 

    @Decorator 
    def test(self, value): 
     self.value = value # change the value of instance 



f = Foo() 
f.test(3) 
print(f.value) # prints 3 


g = Foo() 
g.test(8) 
print(g.value) # prints 8 

または を得たが何f.test.valueこの

def preJob(function): 
    def updateToDo(self, *args, **kwargs): 
     # do some recording 
     function(self, *args, **kwargs) 
    return updateToDo 

class Foo(object): 
    def __init__(self): 
     self.value = 0 

    @preJob 
    def test(self, value): 
     self.value = value 

f = Foo() 
f.test(3) 
print(f.value) # prints 3 


g = Foo() 
g.test(8) 
print(g.value) # prints 8 
関連する問題