闭包
将数据封装在一个包(区域)内,使用时再去里面取(本质上闭包时基于函数嵌套搞出来一个中特殊嵌套)
闭包的应用场景:
1. 封装数据防止污染全局
2.封装数据封到一个包里,使用的时候再取
def tesk(a):
def inner():
print(a)
return inner
v1 = tesk(1)
v2 = tesk(2)
v3 = tesk(3)
v1() # 1
v2() # 2
v3() # 3
装饰器
实现原理:基于@语法和函数闭包,然后将函数赋值给一个新的函数(内层函数),执行函数时再去内层函数中执行闭包中的原函数
实现效果:可以在不改变原函数内部代码和调用代码,实现函数执行和执行扩展功能
适用场景:多个函数系统统一在执行前后自定义一些功能
实例:
查看一个函数的运行时间:
import time
def outer(orgin):
def inner(*args, **kwargs):
old_time = time.time()
res = orgin(*args, **kwargs)
new_time = time.time()
print(f"运行时间{new_time - old_time}")
return res
return inner
@outer
def fun1():
print("我是fun1函数")
time.sleep(3)
value = (11, 22, 33, 44)
return value
fun1()
# 我是fun1函数
# 运行时间3.000948429107666
被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,Python的functools包中提供了一个wraps来消除这样的副作用。写一个装饰器r的时候,最好在实现之前加上functools的wrap,它能保留原有函数的名称和函数属性
import functools
def auth(func):
@functools.wraps(func) # 将原函数的函数名赋值给__name__和注释赋值给__doc__(inner.__name__=admin.__name__)
def inner(*args, **kwargs):
res = func(*args, **kwargs)
return res
return inner
@auth
def admin():
"""hello"""
print(123)
@auth
def rbac():
print("abc")
# 函数名+()
# admin()
print(admin.__name__) # 获取函数名
print(admin.__doc__) # 获取注释
# rbac()