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

Python:在decorator中使用可调用对象而不是本地函数作为包装器,python,python-decorators,Python,Python Decorators,我知道如何在decorators中使用本地定义的函数。我在下面的decorator1中这样做 然而,我发现它不是很干净,而且我也经历过它的酸洗问题 因此,我希望我的装饰程序返回一个可调用的对象。但是,我遇到了一些问题:如果我执行以下代码 def decorator1(f): def wrapped(*args,**kwargs): print(f,' is being called with ',args,kwargs) return f(*args,**

我知道如何在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)
我明白了

正在使用(,0){}调用

正在使用(0,){}调用
回溯(最近一次呼叫最后一次):
文件“/home/wolfersf/Dropbox/Professional/Projects/swutil/swutil/test.py”,第28行,在
a、 二(0)
文件“/home/wolfersf/Dropbox/Professional/Projects/swutil/swutil/test.py”,第15行,在调用中__
返回self.f(*args,**kwargs)
TypeError:foo2()缺少1个必需的位置参数:“x”
似乎
调用的
*args
中没有传递
a

我本以为
a.foo2(0)
翻译成
(a,0)
翻译成
(a,0)
翻译成
(a,0)
翻译成
(a,0)


我做错了什么

覆盖
\uuuu get\uuuu
如下所示即可完成此项工作,尽管我仍然不清楚我最初尝试失败的确切原因

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)

这确实是正确的解决办法。至于为什么没有它就无法工作,您必须了解Python如何将函数转换为方法,下面将对此进行解释:。如果你看了这篇文章后仍然不清楚,请告诉我,我会发布一个完整的答案。我想我理解了,而且我的思想链的第一部分已经错了:
a.foo2
a时没有翻译成
(a,0)
。\u dict\uuuuuu2'.
包装的一个实例。只有当
a.\uuu dict\uuuuu['foo2']
类型为
函数时,或者当我们为其配备手动翻译的
\uu get\uuuuu
方法时,才会发生这种翻译
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)