闭包函数 装饰器
闭包函数
顾名思义就是定义在函数内部的函数,内部函数引用了外部函数作用域的名字
def outter(): x = 111 def inner(): print(x) return inner res = outter() # res就是inner函数内存地址 def func(): x = 333 res() func() # 返回的还是111 # 因为在定义阶段就已经固定了
# 补充:像inner这样虽然他的x调用的是全局的,
# 但他的y引用了外部函数名称空间作用域的名字,
# 且他是定义在函数内部的函数,
# 所以依然是满足闭包函数的两点要求的,所以也是闭包函数 x = 111 def outer(): y = 222 def inner(): print(x,y) return inner
给函数体传参有两种方式
1. 传参
def index1(username): # 这里的username就是变量名,也可以说是参数
print(username) # 这样就往函数体内传入了参数
2. 闭包
def outter(x,y): def my_max(): if x > y: return x return y return my_max res1 = outter(1,40) # res1就是my_max函数的内存地址 print(res1()) # 40 print(res1()) # 40 res2 = outter(90,200) # 这里的res2也是my_max函数的内存地址 # 虽然之前已经传了值了 # 但是在上一句代码执行结束后 # 关系解除,这里又建立了新的关系。 print(res2()) # 200 print(res2()) # 200 print(res2()) # 200
需要注意传参和闭包的使用场景:
1. 直接传参,可能会是在全局中定义,占用变量名,当项目较大,要传参数过多时,
不推荐使用这个方法,只在小项目中可以使用。
2. 闭包传参,特点是只给内部传参,在局部定义变量名,而不是全局,比较安全,起名也方便。
装饰器
就是用来装饰的工具,就是给被装饰的对象添加新的功能,并且不改变原来的使用方法。
装饰器的使用要遵循开放封闭原则
开放:对扩展开放
封闭:对修改封闭
装饰器(装饰器也是可调用对象callable=True)必须遵循的两个原则:
1. 不改变被装饰对象源代码
2. 不改变被装饰对象(必须是可调用对象)调用方式
补充:
# 统计函数运行时间的方法
1.
import time
print(time.time())
# 返回的是 时间戳 即当前时间距离1970-1-1 00:00:00相差的秒数
2.
time.sleep(3)
#让程序暂停三秒再运行
装饰器简单版本
import time def index(): time.sleep(3) print('过了三秒,我开始执行了') def outter(func): # func = 最原始的index函数的内存地址 def get_time(): start = time.time() func() # func = index函数的内存地址() 直接调用 end = time.time() print('index run time:%s'%(end-start)) return get_time index = outter(index) # outter(最原始的index函数内存地址) # index指向get_time函数的内存地址 index()
import time
def index01():
time.sleep(3)
print('过了三秒,我开始执行了')
def outter(func): # func = 最原始的index函数的内存地址
def get_time():
start = time.time()
func() # func = index函数的内存地址() 直接调用
end = time.time()
print('index99 run time:%s'%(end-start))
return get_time
index99 = outter(index01) # outter(最原始的index函数内存地址)
# index指向get_time函数的内存地址
index99()
装饰器语法糖
会将紧挨着它的可调用对象的名字当做参数自动传入调用outter
@outter # 等价于outter(index)
def index():
pass
无参装饰器
from functools import wraps def outter(func): @wraps(func) def inner(*args,**kwargs): # * **在形参中使用 # 执行被装饰函数之前你可以做的操作 res = func(*args,**kwargs) # * **在实参中使用 # 执行被装饰函数之后你可以做到操作 return res return inner @outter def index(username,*args,**kwargs): """index注释""" pass print(index)
########## 补充-重要 ########## wraps方法 # 有以下两个作用 # 1.返回原来的函数的函数名 # 2.返回原来的函数的注释 使用方法就是 首先调用 from functools import wraps 然后在最内层函数正上方 加上 @wraps(func)
有参装饰器(最复杂就三层)
def wrappers(data): # data = 'file' def outter(func): def inner(*args,**kwargs): if data == 'file': # 执行被装饰函数之前你可以做的操作 res = func(*args,**kwargs) # * **在实参中使用 # 执行被装饰函数之后你可以做到操作 return res return inner return outter
装饰器的嵌套
1. 装饰的时候,从下往上
2.执行的时候,从上往下
@outter1 # index = outter1(func2) @outter2 # func2 = outter2(func1) @outter3 # func1 = outter3(index) def index(): pass