class decorator: def __init__(self,func): wraps(func)(self) self.func = func def __call__(self, *args, **kwargs): return self.func(*args, **kwargs) def __get__(self, instance, owner): # 如果不是通过对象来调用的 if instance is None: return self else: return types.MethodType(self, instance) class cls: @decorator def method(self, x, y): return x + y c = cls() print(c.method(3, 4)) # 调用__get__后调用__call__
types.MethodType(self, instance)是不是不对,第一个参数是函数,第二个参数是对象,这里怎么是self
types.MethodType 的底层是用 C 语言实现的,它在处理第一个参数时,并不严格检查它是不是一个普通的 def 函数,它只检查这个对象是不是“可调用的(Callable)”。decorator 类中,self 实现了 __call__ 方法,所以 self 本身就是一个可调用对象。当 MethodType(self, instance) 被触发时,Python 内部会把这个 self 当作一个“类似函数的东西”来对待,并成功将它与 instance c.method(3, 4) 触发了绑定方法的调用。c 塞进去,相当于调用了:装饰器实例.__call__(c, 3, 4)。__call__ 方法内部,此时 *args 的值变成了 (c, 3, 4)。self.func(*args, **kwargs),也就是执行了:原始方法(c, 3, 4)。def method(self, x, y): 完美接收了这三个参数:self=c, x=3, y=4。3 + 4 = 7装饰器实例对象传到了 __call__ 的第一个参数 self,而 c 传到了 *args 里def __call__(self, *args, **kwargs):
decorator_instance.__call__(c, 3, 4) ,位置参数 (c, 3, 4) 👉 全部打包进了 *args
return self.func(c, 3, 4),c 才作为第一个参数传给了原始的 method 函数,并被原始函数的 self 接收