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可以查看指定函数的注释信息

浙公网安备 33010602011771号