2017-11-22 3 views
0

デコレータでローカルに定義された関数を使用する方法を知っています。私は以下のdecorator1でこれを行います。Python:デコレータ内のラッパーとしてローカル関数の代わりに呼び出し可能オブジェクトを使用する

しかし、私はそれが非常にきれいであるとは思わないし、私はそれに酸洗問題を経験した。

私はデコレータが呼び出し可能オブジェクトを返すようにしたいと思います。私は次のコード

def decorator1(f): 
    def wrapped(*args,**kwargs): 
     print(f,' is being called with ',args,kwargs) 
     return f(*args,**kwargs) 
    return wrapped 

def decorator2(f): 
    return Wrapped(f) 

class Wrapped(): 
    def __init__(self,f): 
     self.f=f 
    def __call__(self,*args,**kwargs): 
     print(self.f,' is being called with ',args,kwargs) 
     return self.f(*args,**kwargs) 

class A(): 
    @decorator1 
    def foo1(self,x): 
     return x+1 

    @decorator2 
    def foo2(self,x): 
     return x+1 

a=A() 
a.foo1(0) 
a.foo2(0) 

を実行すると、私は

<function A.foo1 at 0x7efe64641f28> is being called with (<__main__.A object at 0x7efe65b3b3c8>, 0) {} 
<function A.foo2 at 0x7efe6464c0d0> is being called with (0,) {} 
Traceback (most recent call last): 
    File "/home/wolfersf/Dropbox/Professional/Projects/swutil/swutil/test.py", line 28, in <module> 
    a.foo2(0) 
    File "/home/wolfersf/Dropbox/Professional/Projects/swutil/swutil/test.py", line 15, in __call__ 
    return self.f(*args,**kwargs) 
TypeError: foo2() missing 1 required positional argument: 'x' 

を得ることがa<Wrapped_instance>.__call__*argsで渡されていないようだ。しかし、私は問題に実行しています。

私はa.foo2(0)<a.foo2>(a,0)に変換することを考えているだろうが<Wrapped_instance>(a,0)に変換<Wrapped_instance>.__call__(a,0)に変換私は間違って何をやっている<<Wrapped_instance>.__call__>(<Wrapped_instance>,a,0)

に変換?

答えて

0

私は元の試行が失敗した理由はまだ分かりませんが、__get__を上書きすると、その仕事ができます。

class Wrapped(): 
    def __init__(self,f): 
     self.f=f 
    def __call__(self,*args,**kwargs): 
     print(self.f,' is being called with ',args,kwargs) 
     return self.f(*args,**kwargs) 
    def __get__(self,obj,type=None): 
     return functools.partial(self,obj) 
+1

これは本当に適切な解決策です。それがうまくいかなかった理由については、Pythonが関数をメソッドに変換する方法を理解する必要があります。これについては、ここで説明します:https://wiki.python.org/moin/FromFunctionToMethodこの文書を読んだ後もまだ不明な点がある場合は教えてください。完全な回答を投稿します。 –

+1

私は思っています。私の思考連鎖の最初の部分は間違っていたと思います。 'a.fict2'は' a .__ dict __ ['foo2']>(a、0) 'foo2'] 'は' Wrapped'のインスタンスです。この変換は 'a .__ dict __ ['foo2']'が 'function'型であるとき、または手作業で翻訳を行う' __get__'メソッドを装備するときにのみ起こります – Bananach

関連する問題