Python 装饰器为什么难理解?
我觉得不难理解啊。
# 函数封装与调用
一般情况下,我们会把成套的代码封装成一个一个的函数,这样方便我们调用。
def 我是函数呀():
print('hello world !')
# 直接调用函数
我是函数呀()
这一段代码很直接,就是 hello world !
中间商
现在我们加个中间商角色,通过中间商来调用函数。如下:
def 我是中间商(函数: callable):
return 函数
def 我是函数呀():
print('hello world !')
# 调用中间商
我是中间商(我是函数呀)()
这个代码和上面的直接调用函数的代码,运行结果是一样的,但代码有点脱裤子放屁了。
其实,我们有了中间商的角色,我们就可以在中间商环节里动手脚了,例如我们在中间商里加点盐,代码如下:
def 我是中间商(函数: callable):
print('没想到吧,我给你加点盐')
return 函数
def 我是函数呀():
print('hello world !')
def 我也是函数呀():
print('hello world again !')
# 调用中间商
我是中间商(我是函数呀)()
print('-' * 50)
我是中间商(我也是函数呀)()
中间商代码在执行函数前,加了点盐。我们代码中通过中间商调用了两个函数,这两个函数都加了盐。
所以你可以通过中间商在函数执行前做一些共性的操作,例如 打印log。中间商还是很有用的。这一点都不脱裤子放屁。
中间商有点麻烦
我们通过 我是中间商(我是函数呀)()这种格式调用函数,总是多写了 我是中间商 这部分调用,并且这种通过中间商调用函数的格式是完全统一的,有没有什么办法让他自己把中间商套上呢?
答案是有的,既然格式是完全统一的,编译器/解释器 给我们做了个语法糖,通过在函数定义前面加个 @ 符号,编译器/解释器自动在调用函数函数时,转换成 我是中间商(我是函数呀)()这种格式。像这种:
# 装饰器
@我是中间商
def 我是函数呀():
print('hello world !')
作为对比,以下代码中两个方法,两种不同的调用方式,效果是一样的。
def 我是中间商(函数: callable):
print('没想到吧,我给你加点盐')
return 函数
@我是中间商
def 我是函数呀():
print('hello world !')
def 我也是函数呀():
print('hello world again !')
# 调用中间商
我是函数呀()
print('-' * 50)
我是中间商(我也是函数呀)()
我是函数呀前面加了 @我是中间商,这相当于告诉了编译器/解释器,我在调用 我是函数呀的时候,你帮我套个 我是中间商的壳,这样就避免了手动套壳(重复的工作总是那么的low)。
下图的运行结果也证明了,自动套壳,和手动套壳,效果是一样的。
另外,我们注意到,通过 @ 告诉编译器/解释器 来自动套壳,让我们在调用函数时,保留了函数原始的形态,原汁原味的函数,总是那么的舒心。
@我是中间商 这就是装饰器
推而广之
以上就是装饰器的简单形态了。
其实你也看到了,不可能所有的函数都没有参数,如果函数有参数怎么办?
其中,有了基础形态,为了支持带参函数的装饰,甚至中间商本身也带参数,都是支持的。为了支持这些特性, 装饰器的定义演化出了一层又一层壳。但万变不离其宗,装饰器本质就是个中间商,不能因为它穿上了华贵的衣服,你就不认识它了。
最后
最后,补个图吧,通过 print 对齐打印的方式,打印条形图。