Day13课后有感
今日内容概要
-
-
闭包函数的实际应用
-
装饰器简介(重点+难点)
-
简易版本装饰器
-
进阶版本装饰器
-
完整版本装饰器
-
装饰器模板(拷贝使用即可)
-
装饰器语法糖
-
装饰器修复技术
# 闭包函数的两大特征 1.闭:定义在函数内部的函数 # 函数内的嵌套函数,只能在函数内部用 2.包:内部函数使用了外层函数名称空间中的名字 # 函数内的嵌套函数访问了外层函数的变量 def outer(): x = 999 def inner(): # 嵌套函数 print('from outer>>>inner',x) return inner #有返回值 x = 666 res = outer() # 访问外层函数 res()
闭包函数的实际应用
闭包函数是给函数体传参的另外一种方式
函数体传参的方式1: 形参
def index(username): print(username) index('jason') # jason就是给index变量名传参,参数都是自定义的,传什么看你心情~
函数体传参的方式2:闭包
def outer(username): def index(): print(username) return index res = outer('kevin') # 形参username与值kevin临时绑定 >>>:outer局部名称空间中 res() res1 = outer('jason') # 形参username与值kevin临时绑定 >>>:outer局部名称空间中 res1()
定义:
在不改变被装饰函数原有的'调用方式'和'内部代码'的情况下给被函数添加新的功能,只能提添加功能,不能修改原有代码。
什么是时间戳?
import time print(time.time()) # 1647568920.168808 '''上述的注释数字是时间戳:1970年1月1日0时0分0秒距离刚刚代码运行间隔的秒数''' time.sleep(3) # 让程序原地等待三秒 print('hello world')
运用时间戳统计程序执行的时间
import time def index(): time.sleep(3) # 让程序原地等待三秒 print('666') '''给index函数增加了一个统计执行时间的功能''' start_time = time.time() # 函数执行之前获取一个时间戳 index() end_time = time.time() # 函数执行之后获取一个时间戳 print(end_time - start_time) # 两个时间戳的差值就是函数的执行时间
import time def index(): time.sleep(1) print('666') def home(a): time.sleep(3) print('666') print(home) def outer(func): # 真正的index被outer局部名称空间存储了 def get_time(): start_time = time.time() # 函数执行之前获取一个时间戳 func() # 调用了真正的index函数 end_time = time.time() # 函数执行之后获取一个时间戳 print(end_time - start_time) # 两个时间戳的差值就是函数的执行时间 return get_time # res = outer(index) # 左侧的res就是一个普通的变量名 # res() # a = outer(index) # 左侧的a就是一个普通的变量名 # a() # b = outer(index) # 左侧的b就是一个普通的变量名 # b() # index = outer(index) # index() # 看似调用的index其实调用的是get_time # print(index) # 全局名称空间中的index指向的是get_time函数体代码 home = outer(home) # 狸猫换太子
# 解决的是参数问题 def outer(func): def get_time(*args, **kwargs): # 括号内运用到可变长参数 start_time = time.time() func(*args, **kwargs) end_time = time.time() print(end_time - start_time) return get_time
# 解决的是返回值问题
def outer(func):
def get_time(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs) # 执行真正的index函数
end_time = time.time()
print(end_time - start_time)
return res
return get_time
'''编写装饰器其实有一套固定的代码 这套你拿着走哪用哪,随用随调''' def outer(func): # func用于接收被装饰的对象(函数) def inner(*args, **kwargs): print('执行被装饰函数之前 可以做的额外操作') res = func(*args, **kwargs) # 执行真正的被装饰函数 print('执行被装饰函数之后 可以做的额外操作') return res # 返回真正函数的返回值 return inner
语法糖内部原理:
1.使用的时候最好紧跟在被装饰对象的上方
2.语法糖会自动将下面紧挨着的函数名传给@后面的函数调用
# 仅仅是让代码编写的更加好看、简洁!!!
def outer(func): def inner(*args, **kwargs): print('执行函数之前的操作') res = func(*args, **kwargs) # 额外操作 return res return inner @outer # 等价于 index = outer(index) 就这????一个@就搞定了???? def index(*args, **kwargs): print('from index') # index = outer(index) # 总感觉这一行代码有点low!!! @outer # 等价于 home = outer(home) def home(*args,**kwargs): print('from home') print(index) print(home)
from functools import wraps # 照抄即可 def outer(func): @wraps(func_) # 照抄即可
def inner(*args, **kwargs): print('执行被装饰对象之前可以做的操作') res = func_name(*args, **kwargs) return res return inner @outer def index(): print('from index') @outer def home(): '''这是home函数的注释''' print('from home') # help(home) # help可以查看指定函数的注释信息