今日内容总结
一、闭包函数
二、闭包函数的实际应用
三、装饰器简介
四、简易版本装饰器
五、进阶版本装饰器
六、完整版本装饰器
七、装饰器模板(很重要)
八、装饰器语法糖
九、装饰器修复技术
一、闭包函数
# 闭包函数的两大特征
1、闭:定义在函数内部的函数
2、包:内部函数使用了外层函数名称空间中的名字
eg:
def outer():
x = 111
def inner():
print('form outer>>>inner',x)
return inner
x = 222 # 结果和这个x = 222没有关系
res = outer()
res() # 111
二、闭包函数实际应用
# 闭包函数是给函数传参的另外一种方式
函数体传参的方式:
1、形参:
def index(username):
print(username)
函数体代码需要什么就可以在形参中写什么
index('owen')
2、闭包
def outer():
username = 'owen'
def index():
print(username)
return index
res = outer()
res() # owen
#当这个闭包里只写了Owen,那就会一直使用owen
def outer(username):
def index():
print(username)
return index
res = outer('mary') # 形参username与值mary临时绑定到outer局部名称中
res() # mary
res1 = outer('owen')# 形参username与值owen临时绑定到outer局部名称空间里面
res1() # owen
# 想要修改参数,就重新定义一个值,进行重新绑定
三、装饰器简介
装饰器的本质:
例如给函数index装饰
在不改变index原有的'调用方式'和'内部代码'的情况下给index添加新的功能
装饰器的原则:
"""对外扩展开放,对修改封闭"""
import time(调用模块)
print(time.time()) # 1647589902.705415
# 获取的数字就是时间戳:1970年1月1日0时0分0秒距离刚刚代码运行间隔的秒数
time.sleep(3) # 让程序原地休眠三秒
print('hello world')
print(time.time())
# hello world
# 1647590604.362981
import time
def index():
time.sleep(3)
print('from index')
start_time = time.time() # 函数执行之前获取的时间节戳
index()
end_time = time.time() # 函数执行之后获取一个时间戳
print(end_time - start_time) # 用第二个时间戳减第一个时间戳,结果就是函数的执行时间
四、简易版本装饰器
'''给index函数增加了一个统计执行时间的功能'''
def index():
time.sleep(1)
print('from index')
start_time = time.time() # 函数执行之前获取一个时间戳
index()
end_time = time.time() # 函数执行之后获取一个时间戳
print(end_time - start_time) # 两个时间戳的差值就是函数的执行时间
# 这个只能给一个函数增加功能
import time
def index():
time.sleep(1)
print('from index')
def home():
time.sleep(3)
print('from home')
print(home)
def outer(func):
def get_time():
start_time = time.time() # 函数执行之前获取一个时间戳
func() # 调用了真正的index函数
end_time = time.time() # 函数执行之后获取一个时间戳
print(end_time - start_time) # 两个时间戳的差值就是函数的执行时间
return get_time
home = outer(home) # 狸猫换太子
home()
print(home)
五、进阶版本装饰器
# 解决的是参数问题
def out (func_name):
def get_time(*args, **kwargs):
start_time = time.time() # 开始获取一个时间
func_name(*args, **kwargs)
end_time = time.time() # 结束获取一个时间
print(end_time - start_time)
return get_time
# 这个主要可以改变参数,参数的类型都可以
六、完整版装饰器
# 解决的是返回值问题
import time
def index(username):
time.sleep(3)
return username
def outer(func_name):
def get_time(*args, **kwargs): # 可变长形参,什么数据类型都可以
start_time = time.time()
res = func_name(*args, **kwargs) # 执行真正的index函数
end_time = time.time()
print(end_time - start_time)
return res # 返回原函数的值,没有的时候返回的是none
return get_time
index = outer(index)
res = index('起飞')
print(res)
七、装饰器模板
# 兄弟们,这才是关键
def outer(func_name): # func_name用于接收被装饰的对象(函数)
def inner(*args, **kwargs):
print('执行被装饰函数之前 可以做的额外操作')
res = func_name(*args, **kwargs) # 执行真正的被装饰函数
print('执行被装饰函数之后 可以做的额外操作')
return res # 返回真正函数的返回值
return inner
八、装饰器语法糖
# 语法糖内部原理
1、使用时最好紧跟在被装饰对象上面
2、语法糖会自动将下面紧挨着的函数名床给@后面的函数调用
# 先定义一个outer函数
def outer(func_name):
def inner(*args, **kwargs):
print('执行函数之前的操作')
res = func_name(*args, **kwargs)
# 额外操作
return res
return inner
# 使用outer直接@加outer
@outer # 等价于 index = outer(index)
def index(*args, **kwargs):
print('from index')
print(index)
@outer # 等价于 home = outer(home)
def home(*args,**kwargs):
print('from home')
print(home)
九、装饰器修复技术
from functools import wraps # 固定搭配
def outer(func_name):
@wraps(func_name) # wraps模块warps关键字可以把真函数的属性提取出来,赋值给装饰器,达到以假乱真的地步
def inner(*args, **kwargs):
print('执行被装饰对象之前可以做的操作')
res = func_name(*args, **kwargs)
return res
return inner
@outer
def home():
'''这是函数的注释'''
print('from home')
home()
print(home)
help(home)
# 结果为
from home
<function home at 0x00000249C8FDFCA0>
Help on function home in module __main__: