Decorator 的本质是什么?
decorator 本质就是一个接收对象的对象(对,是个对象,而不是大多数人认为的函数),更多的资料可以参照 理解Python的装饰器 | Darkof
|
|
被装饰的函数与之前相比,改变了什么?
行为
这个是最显而易见的,装饰器可以在原函数执行之前或之后添加额外的行为
函数本身的属性
如果你简单的实现了下面的 decorator 会改变什么呢
|
|
从上面我们看出来,函数的 __name__ 属性也发生了变化,这也是为什么我们推荐装饰器的时候使用 fucntools.wraps
|
|
wraps 会把原函数的属性赋给新的 wrapped 这个函数(主要会同步的属性为 __name__, __module__, __doc__, __dict__, 当然,你也可以添加你希望同步的属性)
函数的参数
是的,很少有人会注意到被装饰过会,函数接收的参数也会产生变化
|
|
f1 接收的函数名从 a 变成了 args 和 kwargs, f2 干脆就拿不到了,这也意味着其实装饰器并不能做到 works anywhere(毕竟有很多装饰器会通过参数来判断这是不是一个 classmethod,然后两个装饰器混用可能会导致其中一个失效)
装饰 classmethod/staticmethod
|
|
当我们尝试用之前实现的 decorator 来装饰 classmethod 的时候,会遇到 TypeError,原因是 classmethod/staticmethod 本质是一个 Descriptor 而非 function,我们在一开始提到这样一句话:
decorator 本质就是一个接收对象的对象
在前面也聊到了,decorator 是个对象,可能是个 class 或是 function, 那么他接收的是什么呢,很多人认为 decorator 接受的是函数,然而严格来说,decorator 接收的是一个对象
当我们知道 classmethod/staticmehtod 是 Descriptor 之后就很容易的知道如何写一个装饰 Descriptor(当然,你需要先了解什么是 Descriptor)
|
|