装饰器被称为与装饰器不同的类是函数吗?

时间:2011-07-07 13:30:07

标签: python-3.x decorator

考虑以下装饰器

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__方法。

为什么会出现这种差异?还有一种方法可以在我的班级风格装饰器中获取对象吗?

1 个答案:

答案 0 :(得分:2)

绑定到实例方法的第一个参数的

self仅适用于因为方法包含在descriptors中。当请求obj.meth,在对象中找不到然后在类中找到时,使用包括对象在内的一些信息调用描述符的__get__方法,并返回实际方法对象周围的包装器,当调用,使用对象调用底层方法作为additonal / first参数(self)。

这些描述符仅为实际功能添加,而不是为其他可调用对象添加。要使使用__call__方法的类像方法一样工作,您必须实现__get__方法(请参阅上面的链接)。