Python 复杂的装饰器,在Python中,可以使用如下命令创建更复杂的函数:
@f_wrap
@g_wrap
def h(x):
something
在Python中,可以任意堆叠装饰器来修改其他装饰器返回的结果,其含义有点类似于 f o g o h(x)
。最终得到的函数名称仍然是 h(x)
。由于存在这种潜在的混淆,因此在创建包含深度嵌套装饰器的函数时要格外小心。如果仅为处理一些横切关注点,那么应该把每个装饰器都设计成能处理单独问题,而且不会造成太多混乱。
另外,如果使用装饰器来创建复合函数,那么最好使用以下几类定义:
from typing import Callable
m1: Callable[[float], float] = lambda x: x-1
p2: Callable[[float], float] = lambda y: 2**y
mersenne: Callable[[float], float] = lambda x: m1(p2(x))
这里每个变量都有一个类型提示用于定义关联函数。m1
、p2
和mersenne
这3个函数都具有Callable[[float], float]
类型提示,表明该函数将接收一个可以被强制转换为浮点数并返回数字的数字。使用类似于F_float = Callable[[float], float]
的类型定义可以避免类型定义上过分简单的重复。
如果函数规模比简单表达式大,强烈建议使用def
语句,这里使用匿名函数对象是比较罕见的情况。
尽管装饰器可以实现很多事情,但需要弄清楚使用装饰器是否能编写出清晰、简洁且易读的代码。在处理横切关注点时,装饰器特性通常与被装饰函数存在本质区别,它极大地简化了被封装的函数。通过装饰器添加日志记录、调试或安全检查是常见的做法。
然而对于过于复杂的装饰器设计,一个严重的后果是难以提供适当的类型提示。当类型提示退化为只能使用Callable
和Any
时,这样的设计可能会变得晦涩难懂。