闭包
闭包条件,函数内的函数,内函数引用外函数的局部变量。目的,减少全局变量的使用,更具有封装性。
为什么呢?
这首先取决于Python的一个特性,如果函数有默认参数,那么它只会在本次程序的开始初始化一次,也就是说,它相当于这个函数内部的静态变量。那么我们在这场游戏中,行走时便可以保持一个持续移动的状态,而非在一段距离内回流。
1 #一个游戏内人物行走栗子 2 3 x_max=100 4 x_min=-100 5 y_max=100 6 y_max=-100 7 8 def creat(x=0,y=0): #xy代表初始位置 9 def walk(D,step): #D代表方向,1左(上)-1右(下)0不动 10 nonlocal x,y 11 x+=D[0]*step 12 y+=D[1]*step 13 if x>x_max: 14 x=200-x 15 elif x<x_min: 16 x=-100-x 17 if y>y_max: 18 y=200-y 19 elif y<y_min: 20 y=-100-y 21 return walk
另,一般设计程序时,本着一个函数只做一件事的原则,那么闭包也会派上用场。
装饰器
这也是闭包的应用,不过引出这个是为了引出另外一个新内容。@语法糖
1 def log(func): 2 def wrapper(): 3 print("begin to run the function of eat()") 4 func() 5 print("end to run the function of eat()") 6 return wrapper 7 def eat(): 8 print("I'm eating!") 9 10 >>log(eat)
def log(func): def wrapper(): print("begin to run the function of eat()") func() print("end to run the function of eat()") return wrapper @log def eat(): print("I'm eating!") >>eat()
引入语法糖之后,直接调用eat便可以完成log的调用。
如果eat有参数,那么可以将eat的参数丢给wrapper。来达到传参的目的。但是这样有一定的弊端,wrapper必须与eat的参数数量一致,同时修改。
1 def log(func): 2 def wrapper(*params): 3 print("...") 4 func(*params) 5 print("...") 6 return wrapper
通过定义的时候收集参数打包到元祖中,然后调用时用星号进行解包,这样无论eat有多少参数都可以一并接取。
在此延伸一下,*a,可以传入除了dict之外的任何未命名参数,**a除此之外还可以传入字典参数。
除此之外,一个函数可以加不同的装饰器。