一、函数闭包
在函数内部再定义一个函数,并且这个函数用到了外部函数的变量,那么将这个函数以及用到的一些变量称之为闭包。
def line_conf(a, b):
def line(x):
return a*x + b
return line
#调用
line1 = line_conf(1, 1)
line2 = line_conf(4, 5)
print(line1(5))
print(line2(5))
在此函数中,函数line和变量a,b构成闭包。在调用过程中,传入不同的a,b就相当于不同的函数y=ax+b;所以提高了代码的可重复利用性。
二、初识装饰器
假设:初始情况下,我们有100个函数F1~F100现在要在这100个函数之前加入一个功能W1。
def F1():
pass
def F2():
pass
def W():
pass
def Decorator(func):
def W():
pass #功能W
func()
return W
由于有100个函数,我们不会一个一个加上功能W在每个函数的前面,这时候可以借助函数Decorator,在函数Decorator中传入参数func。这样就可以在每次调用函数F1~F100时候传入函数名就可以了。在调用过程中如下:
F=Decorator(Fx)
F()
因为函数Decorator是一个函数闭包,返回的是一个函数。所以有一个变量去接收然后才能去调用。
三、再识装饰器
由于上述的调用方法,需要两步,而且调用方法中的名字“F”不同人写的代码可能是不一样的,这样再给别人调用时候就会出现麻烦。这时候就可以使用,我们看到的那种带@的方式。(Python的语法糖)
def Decorator(func):
def W():
pass #功能W
func()
return W
@Decorator
def f1():
pass
@Decorator
def f2():
pass
就是在每个函数之前加上一个@Decorator。这样的话,调用时候就是
F1()
F2()
所以加上 @闭包函数 就相当于两步
F=Decorator(Fx)
F()
python解释器是从上到下解释代码,步骤如下:
1. def Decorator(func): ==>将Decorator函数加载到内存
2. @Decorator
@函数名 是python的⼀种语法糖。
@Decorator内部是这样执行的:首先执行Decorator函数,并将@Decorator下面的函数f1作为函数Decorator的参数
即@Decorator等价Decorator(F)。然后将执行完的Decorator函数返回值 赋值 给@Decorator下面的函数的函数名F即将Decorator的返回值再重新赋值给 f1 即:
F = def W():
#验证 1
#验证 2
#验证 3
F()
return W
所以在以后执行时候直接调用F()即可。
四、装饰器的运行顺序
下面看看当有两个装饰器时候的调用结果
def Decorator1(func):
def W1():
print("---1---")
return "B"+func()+"B"
return W1
def Decorator2(func):
def W2():
print("---2---")
return "A"+func()+"A"
return W2
@Decorator1 #f1=Decorator(f1)
@Decorator2 #f1=Decorator2(f1) 由后往前看
def f1():
print("----f1------")
return "hello"
result=f1()
print(result)
#-----------------
---1---
---2---
----f1------
BAhelloAB
[Finished in 0.3s]
python解释器由上至下,装饰器最终还是一个函数.
当有多个装饰器时候,由上至下装饰,
所以先执行Decorator1然后再执行Decorator2。
在调用Decorator1时候,return "B"+func()+"B" ;之后调用了函数func()、且func在下一个装饰器函数Decorator2装饰下再去调用;运行Decorator2函数,再在其中return "A"+func()+"A",这个时候调用的func是没有装饰下的初始f1,所以在Decorator2函数中return AhelloA,在Decorator1中再加上B,最终得到BAhelloAB