闭包
闭包:
1.闭包就是在调用函数结束后,可以持续保存局部变量和形参的一种手段
2.闭包就是为了装饰器做准备的,在现实开发中,闭包的应用场景极少闭包的必备条件:
1. 函数定义的内部嵌套函数的定义
2. 内部函数中使用外部函数的形参或临时变量
3. 外部函数返回内部函数的引用(函数名)
# 函数定义的嵌套
def out_func(num1):
def in_func(num2):
# 内部函数中使用了外部函数的形参
print((num1 + num2))
# 外部函数中返回了内部函数的引用
return in_func
# 请问: 调用外部函数后,我们获得了什么呢???
# 1. 获得了in_func的引用,需要使用变量接收,可以进行调用
# 2. 获得了num1变量的值
# out_func(3) = in_func + 变量num1 = 3
f1 = out_func(3)
print(f1)
f1(5) # 8
f1(2) # 5
# num1 为什么存在呢?
# 因为内部函数引用了外部函数的形参或局部变量,引用计数增加,函数结束后引用计数不为0所以没有被销毁
装饰器
装饰器作用: 给函数增加新的功能
装饰器原则:
1.不修改源代码
2.不修改已有函数的调用方式
3.给函数增加新的功能装饰器的本质,就是一个闭包函数, 闭包的一个重要应用场景就是装饰器
is_login = False
# 函数定义的内部嵌套函数的调用
def login_judge(func):
def func_inner():
# 在函数的内部调用外部函数的形参
# 在函数调用前增加功能
if is_login:
func()
else:
print('请先登录再使用相应功能')
# 返回内部函数的引用
return func_inner
def comment():
"""评论方法"""
print('我是喷子,我要开始评论了')
def create_order():
"""创建订单"""
print('我要开始购物了')
# 1. 使用 闭包可以调用该函数并且不修改源代码
func1 = login_judge(comment)
func1()
# 2.为了不修改原函数的调用方式我们使用原函数的函数名接收装饰后的函数
comment = login_judge(comment)
comment()
# 3.增加新的功能,可以在闭包的内部函数中,增加代码以保证函数功能的增加
# 如果想给其他函数添加装饰器继续装饰即可
create_order = login_judge(create_order)
create_order()
通用装饰器
通用装饰器: 可以装饰所有的函数
函数参数: 为了保证被装饰函数的参数都可以接收到,我们可以使用不定长参数进行接收(*args, **kwargs 可以接收一切参数)
函数返回值: 需要将函数运行的结果进行返回(如果被修饰的函数没有返回值呢? 依然返回)
def func_out(func):
def func_in(*args, **kwargs):
print('此处可以在函数调用前增加新的功能')
result = func(*args, **kwargs)
print('此处可以在函数调用后增加新的功能')
return result
return func_in
@func_out
def func1():
print('我是一个孤独的函数')
func1()
@func_out
def func2(num1, num2):
print(num1 + num2)
func2(3, 4)
@func_out
def func3(num1, num2):
return (num1 + num2)
print(func3(4, 5))
小案例
# 需求: 给函数添加装饰器,当函数运行结束后,执行时间打印到控制台上
# 思路: 在程序运行之前获取时间,在程序运行之后再获取时间 相减求差
import time
# current_time = time.time()
# # 1661677269.5817566 时间戳,精确到毫秒值
# # 时间戳就是从1970年1月1日00:00:00到现在的毫秒值
# print(current_time)
# 创建装饰器
def compute_time(func):
def func_inner(*args, **kwargs):
# 程序开始前计算开始时间
start = time.time()
result = func(*args, **kwargs)
# 程序结束后计算结束时间
end = time.time()
# 输出所用时间
print(f'该程序运行的时间是{end - start}s')
return result
return func_inner
@compute_time
def func1():
print([i * 2 for i in range(1, 1001)])
func1()
@compute_time
def func2():
for i in range(1, 1001):
print(i * 2)
func2()