2011-07-07 4 views
2

デコレータ関数であるデコレータと異なるクラスと呼ばれるデコレータはありますか?

class MethodDecoratorC(object): 
    def __init__(self,func): 
     self.func = func 
    def __call__(self,*args,**kwargs): 
     print(len(args)) 
     print(len(kwargs)) 
     self.func(*args,**kwargs) 

def method_decorator_f(func): 
    def wrapped_func(*args,**kwargs): 
     print(len(args)) 
     print(len(kwargs)) 
     func(*args,**kwargs) 
    return wrapped_func 
彼らは正確に同じことを見て

、そして本当の機能のために次のことを考えてみましょう:

@MethodDecoratorC 
def test_method_c(a): 
    print(a) 

@method_decorator_f 
def test_method_f(a): 
    print(a) 

test_method_f("Hello World! f") 
test_method_c("Hello World! c") 

プリント:方法については

1 
0 
Hello World! f 
1 
0 
Hello World! c 

しかし、非常に何か奇妙なことが起こる:

class TestClass(object): 
    @MethodDecoratorC 
    def test_method_c(self,a): 
     print(a) 

    @method_decorator_f 
    def test_method_f(self,a): 
     print(a) 

t = TestClass() 
t.test_method_f("Hello World! f") 
t.test_method_c("Hello World! c") 

プリント:

2 
0 
Hello World! f 
1 
0 
Traceback (most recent call last): 
    File "test5.py", line 40, in <module> 
    t.test_method_c("Hello World! c") 
    File "test5.py", line 8, in __call__ 
    self.func(*args,**kwargs) 
TypeError: test_method_c() takes exactly 2 arguments (1 given) 

あまり期待されません!何とかTestClassオブジェクトは、私のデコレータオブジェクトの__call__メソッドへの引数として転送されません。

なぜこの違いがありますか?私のクラススタイルのデコレータでオブジェクトを取得できる方法はありますか?

答えて

2

selfは、メソッドがdescriptorsにラップされているため、インスタンスメソッドの最初の引数にバインドされています。 obj.methが要求され、オブジェクトに見つからずにクラス内に見つかると、オブジェクトを含むいくつかの情報と共に記述子の__get__メソッドが呼び出され、呼び出されると、そのメソッドを呼び出す実際のメソッドオブジェクトの周りにラッパーを返します。追加/第1引数としてオブジェクト(self)。

これらの記述子は実際の関数にのみ追加され、他の呼び出し可能オブジェクトには追加されません。 __call__メソッドを持つクラスをメソッドのように動作させるには、__get__メソッドを実装する必要があります(上記のリンクを参照)。

関連する問題