一、闭包
- 满足闭包的条件
1.一个函数定义中嵌套另一个函数的定义
2.内函数中往往会用到外函数中的参数,无论是传递的还是外函数的局部变量(内函数可以访问的外部变量)
3.外函数的返回值为内函数名(函数的引用(指向))
注
①python中定义函数的过程相当于将函数名(也就是变量名)指向一段代码,即函数体
②内函数与外函数共享外函数中的变量值
def line_conf(a, b):
def line(x):
return a*x + b #内函数共享外函数的局部变量
return line
line1 = line_conf(1, 1)
# 此时line1指向line指向的函数体,即line1是一个函数名
line2 = line_conf(4, 5)
#同上
print(line1(5))
#相当于调用line函数
print(line2(5))
二、装饰器
*介绍:*通过装饰器,在原来函数的基础上增添功能,不用修改原函数,也不用改变之前调用函数的调用方式(不改变原函数的情况下修改原函数)
- 对无参数无返回值的函数进行装饰
#无装饰器
#定义函数
def function():
print('我是函数……')
#调用函数
function()
#使用装饰器
def test(fun):
print('我是个装饰器……')
def start_fun():
fun()
print('函数执行完成')
return start_fun
@test # 相当于 function = test(function)
def function():
print('我是函数……')
function()
注
装饰器的功能其实通过改变函数名(变量名)的指向来实现的
函数名原先指向函数体,通过装饰器,函数名指向闭包的内部函数名所指的代码块(即调用原来的函数相当于调用闭包的内部函数)
- 对具有参数的函数进行装饰
def test(fun):
print('我是个装饰器……')
def start_fun(a,b):
fun(a,b)
print('函数执行完成')
return start_fun
@test # function = test(function)
def function(a,b):
print('%d+%d=%d'%(a,b,(a+b)))
function(1,2)
- 对不定长参数的函数进行装饰
#通用方式
def test(fun):
print('我是个装饰器……')
def start_fun(*args,**kwargs): #定义函数时传递的不定长参数
fun(*args,**kwargs) #执行函数时传递的实参是对不定长参数的解包
print('函数执行完成')
return start_fun
@test # function = test(function)
def function(*args,**kwargs):
print('%d+%d = %d'%(args[0],args[1],args[0]+args[1]) )
function(1,2)
注
①对于有参数的函数进行装饰时,一般选择用不定长参数来接受参数值,比较通用
②当args和kwargs不为空时,*args和**kwargs相当于对元组args和字典kwargs解包
- 对具有返回值的函数装饰
def test(fun):
print('我是个装饰器……')
def start_fun(*args,**kwargs):
return fun(*args,**kwargs)
return start_fun
@test # function = test(function)
def function(*args,**kwargs):
return args[0]+args[1]
function(1,2)
注
函数中的return具有终止函数并返回值的功能
- 同一个装饰器对多个函数装饰
def test(fun):
print('我是个装饰器……')
def start_fun(*args,**kwargs):
return fun(*args,**kwargs)
return start_fun
@test # function1 = test(function1)
def function1(*args,**kwargs):
return args[0]+args[1]
print(function1(1,2))
@test # function2 = test(function2)
def function2(*args,**kwargs):
return args[0]-args[1]
print(function2(1,2))
- 注
同一装饰器对不同函数装饰时,会单独复制一份内存空间,用来存储每个使用装饰器的函数的函数名(变量名)所指向的闭包中内函数的代码块 - 不同装饰器对同一函数装饰
def test1(fun):
print('我是个装饰器1……')
def start_fun(*args,**kwargs):
return fun(*args,**kwargs)
return start_fun
def test2(fun):
print('我是个装饰器2……')
def start_fun(*args,**kwargs):
return fun(*args,**kwargs)
return start_fun
@test1
@test2 # function2 = test2(function2)
def function2(*args,**kwargs):
return args[0]-args[1]
print(function2(1,2))
注
执行顺序:test2函数,test1函数,function2函数
即离被修饰函数最近的,依次往外开始执行
- 带有参数的装饰器
def test1(num):
print(num+1)
def test(fun):
print('我是个装饰器……')
def start_fun(*args,**kwargs):
return fun(*args,**kwargs)
return start_fun
return test
@test1(2)
#执行test1函数
# 将test1的返回值(是一个函数名)当作装饰器用来装饰function 相当于function1 = test(function1)
def function1(*args,**kwargs):
return args[0]+args[1]
#调用函数
print(function1(1,2))