闭包
定义:一个函数中再定义一个函数,其中里边的函数用到了外边函数的变量,则称这两个函数为一个闭包。
看一个闭包的例子:
def f1(x):
def f2():
return x+1
return f2
ret = f1(10)
print(ret())
输出:
11
上述代码中,调用f1函数返回的f2函数的引用,即ret指向的是f2的引用,在调用ret时即是调用f2函数。
由于闭包引用了外部函数的局部变量,因此外部函数的局部变量不能及时释放,消耗内存。
装饰器
在不修改原来代码的前提下增加逻辑即可以用到装饰器。
先来看一下装饰器的功能:
1.引⼊⽇志
2.函数执⾏时间统计
3.执⾏函数前预备处理
4.执⾏函数后清理功能
5.权限校验等场景
6.缓存
举个例子:
无参数装饰器:
def func1(func):
def func2():
print("add test logic")
return func()
return func2
@func1
def work_platform():
print("this is work_platform")
work_platform()
输出:
add test logic
this is work_platform
解释一下执行原理:
首先,python解释器从上向下执行代码,func1函数加载到内存中,在执行@func1时python解释器中会执行以下逻辑,将@func1下边的函数名作为func1参数,然后调用func1函数,即func1(work_platform),执行func1函数返回func2的引用,并且将返回值再次赋值给@func1下的函数名,即此时的work_platform指向的时func2函数,这样在调用work_platform时实际上是调用的func2,如果还不明白的话就以代码注释的形式再叙述一遍
def func1(func): # python解释器遇到函数不执行,加载到缓存中
def func2():
print("add test logic")
return func()
return func2
# 执行到@func1的时候会将work_platform函数名作为参数传给func1,调用func1,即func1(work_platform)
# 调用func1函数后返回func2的引用,并将其赋值给work_platform,这样work_platform这个函数就会重新指向另外的函数,这样就会形成以下的形式
# 新work_platform -> def func2():
# print("add test logic")
# work_platform() 这个work_platform是原来指向的函数
# 这样再次调用work_platform函数时,就会调用新的work_platform指向的函数,而不是原来定义的那个函数
@func1
def work_platform():
print("this is work_platform")
work_platform() # 这个work_platform指的是新work_platform
这样一来既增加了验证逻辑,又执行了原来函数的代码
以上这种装饰器由于被装饰的函数没有参数,所以称为无参数装饰器
带参数装饰器:
def func1(func):
def func2(a,b):
print("add test logic")
print("a:{}".format(a))
print("b:{}".format(b))
return func(a,b)
return func2
@func1
def work_platform(a,b):
print("this is work_platform")
print(a+b)
work_platform(1,2)
输出:
add test logic
a:1
b:2
this is work_platform
3
由于work_platform 函数指向的是func2,所以所带的参数也相应的传给func2
通用装饰器:即不论被装饰的函数中存在几个参数,装饰器都可以接受而不报错,所以在func2中使用不定长参数即可。
def func1(func):
def func2(*args, **kwargs):
print("add test logic")
return func(*args, **kwargs)
return func2
@func1
def work_platform(a,b):
print("this is work_platform")
print(a+b)
work_platform(1,2)
给装饰器加参数,即是在装饰器的外边再加一层函数,即在原有装饰器的基础上设置外部变量
def xiaogu(auth):
def func1(func):
def func2(*args, **kwargs):
if auth == "root":
print("auth is big")
elif auth == "user":
print("auth is small")
print("add test logic")
return func(*args, **kwargs)
return func2
return func1
@xiaogu("root")
def work_platform(a,b):
print("this is work_platform")
print(a+b)
work_platform(1,2)
一个函数有多个装饰器的情况:装饰器会自上而下依次执行
def func1(func):
def func2(*args, **kwargs):
print("add test logic")
return func(*args, **kwargs)
return func2
def demo(func):
def func3(*args, **kwargs):
print("demo func3")
return func(*args, **kwargs)
return func3
@func1
@demo
def work_platform(a, b): # 先执行func1装饰器,再执行demo装饰器,最后执行work_platform函数
print("this is work_platform")
print(a + b)
输出:
add test logic
demo func3
this is work_platform
3