Python:使用可调用对象而不是本地函数作为装饰器中的包装器

时间:2017-11-22 11:39:03

标签: python python-decorators

我知道如何在装饰器中使用本地定义的函数。我在下面的decorator1中执行此操作。

但是,我发现它并不干净,而且我遇到了酸洗问题。

我希望我的装饰器返回一个可调用的对象。但是,我遇到了问题:如果我执行以下代码

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未在*args的{​​{1}}中传递。

我原以为<Wrapped_instance>.__call__转换为a.foo2(0)转换为<a.foo2>(a,0)转换为<Wrapped_instance>(a,0)转换为<Wrapped_instance>.__call__(a,0)

我做错了什么?

1 个答案:

答案 0 :(得分:2)

覆盖__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)