闭包函数
简单来说,一个函数定义中引用了函数定义外的变量,并且该函数可以在定义的环境外被执行,外层函数返回内层函数的函数地址(函数体),我们把这样的函数称为闭包函数。
注意:如果返回的函数中没有引用父函数中定义的局部变量,那么返回的函数不是闭包函数。
# 定义一个函数
def func1():
print("世界那么大,我想去看看")
print(func1) # 返回函数地址
"""
返回结果 为func1的内存地址
<function func1 at 0x0000021F96CE77F0>
"""
# 定义一个简单的闭包函数
def func1():
print("世界那么大,我想去看看")
def func2():
print("身上没钱,还是别去了吧")
return func2
# 调用函数
f = func1() # f = func1 = func2
func1()() # f = func1
print(func1) # 打印func1函数的内容 和 func2的内存地址
判断是否是闭包函数
函数 _ _closure _ _,当函数是闭包函数时,返回cell 元素,不是闭包函数时,返回None。
- 返回cell时:
def name():
print("python")
def res():
print("任你选择")
print(res.__closure__) # (<cell at 0x000002A37ABE2AD0: str object at 0x000002A37A8834B0>,)
return res
- 返回None:
name = "小红"
def name_1():
print("python")
def res():
print("name")
print(res.__closure__)
return res
name_1()
"""
返回结果:
python
None
"""
你以为这就完了吗 ?学习闭包就是为了后面的装饰器做准备的。
装饰器 (重点)
装饰器就是一个闭包,装饰器是闭包的一种应用,可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象。
应用场景:插入日志、性能测试、事务处理、缓存、权限校验等。
# 定义一个简单的装饰器
def inout(test):
print("外层代码")
def inter():
print("此处为新添加的代码 1")
test() # 旧代码的位置
print("此处为新添加的代码 2")
return inter # 返回内存函数的地址
# 定义一个需要被修改的旧代码
def old_def():
a = 5
b = 6
c = a + b
print("{}+{}={}".format(a,b,c))
return old_def
# 修改旧代码
inout(old_def)()
"""
输出结果:
外层代码
此处为新添加的代码 1
5+6=11
此处为新添加的代码 2
"""
inout(old_def()) # 执行旧代码后再执行装饰器外层函数,未执行内层函数。
"""
输出结果:
5+6=11
外层代码
"""
注意:当取函数时未添加括号,输出为函数的内存地址 |
**@**符号,用一个简短的方式来生成一个被装饰的函数。
# 计算一个函数的运行所需要的时间
import datetime # 导入datetime模块
def count_time(test):
def inter():
start_time = datetime.datetime.now() # 程序开始时间
print("开始时间为{}".format(start_time))
test() # 程序
end_time = datetime.datetime.now() # 程序结束时间
print("结束时间为{}".format(end_time))
sum_time = end_time - start_time # 结束—开始时间就是共运行时间
print("执行该程序共计:%s" % sum_time)
return inter
格式一: 递归
# 这里将内部函数递归嵌套在一个函数result中,
# 直接获取 1+2+3+...+10 结果,避免函数重复在装饰器中重复调用函数。
@count_time
def result():
def num_sum(x):
if x >= 5:
return 0
else:
return x + num_sum(x+1)
print("这里是个函数num_sum:{}的递归".format(num_sum(1)))
result() # 用 @count_time 方式调用装饰器,调用整个函数就相当方便。
格式二: 循环
n = 0
@count_time
def num_sum():
global n # 声明 使用全局变量
for i in range(101):
n += i # n = n + 1
return print("总数:{}".format(n))
num_sum()
基础的闭包与装饰器我们要掌握,在后面学习中类中还会遇到,不然在学习的可能就会掉崩溃噢。