赞
踩
闭包是嵌套在函数中的函数。
闭包必须是内层函数对外层函数的变量(非全局变量)的引用。
被引用的非全局变量也称作自由变量,这个自由变量会与内层函数产生一个绑定关系。
自由变量不会再内存中消失。
外部函数返回了内部函数
通俗点说:
闭包是一个函数,这个函数是嵌套在另外一个函数里边,且这个函数引用了外层函数的变量(非全局变量)
定义外部函数
定义外部函数,在内部函数中使用外部函数的变量
外部函数返回内部函数的地址(内部函数名就饿内部函数的地址)
- # 定义内部函数:
- def outer(num):
- # 2.定义内部函数,在内部函数中使用外部函数的变量
- def inner(num1):
- print(num + num1)
-
- # 3.外部函数返回内部函数的地址
- return inner # 函数名字就是函数地址
-
-
- if __name__ == '__main__':
- # 创建闭包实例
- func = outer(100) # 此时func相当于是inner
- # 调用闭包
- func(10) # 此时调用inner函数,保存的num值为100
- # 可以创建多个闭包实例,不同的闭包实例之间,不会相互影响
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
需求:
根据配置信息使用闭包实现不同人的对话信息,例如对话:
张三:到北京了吗?
李四:已经到了,放心吧。
实现步骤说明:
定义外部函数接受不同的配置信息参数,参数是人名
定义内部函数接受对话信息参数
在内部函数里面把配置信息和对话信息进行拼接输出
- def outer(name):
- # 定义内部函数,参数是 说话的信息
- print(f'{name}:到北京了吗?')
-
- def inner(name1):
- # 内部函数中,将name和info进行拼接输出
- print(f'{name1}:已经到了,放心吧。')
-
- # 外部函数返回内部函数的地址
- return inner
-
-
- # 创建闭包实例
- if __name__ == '__main__':
- func = outer('张三')
- func('李四')
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
注意点:由于闭包引用了外部函数的变量,则外部函数的变量没有及时释放,消耗内存。
函数内部想要修改全局变量,使用global关键字
在闭包函数内部,想要修改外部函数的局部变量,需要使用nonlocal关键字
- def outer():
- num = 10
-
- def inner():
- # num = 100 # 不是修改外部变量的值,重新定义的局部变量
- nonlocal num # 声明使用外部变量 num 不重新定义
- num = 100
-
- print(f'调用inner之前:{num}')
- inner()
- print(f'调用inner之后:{num}')
- return inner
-
-
- func = outer()
- func()
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
保存局部信息不被销毁,保证数据的安全性
1,闭包只能存在嵌套函数中
2, 内层函数对外层函数非全局变量的引用(使用),就会形成闭包。
- def wrapper():
- a = 1
- def inner():
- print(a)
- return inner
- ret = wrapper()
-
- #例一是闭包
- # 例二:
- a = 2
- def wrapper():
- def inner():
- print(a)
- return inner
- ret = wrapper()
-
- #例二不是闭包
- # 例三:
-
- def wrapper(a,b):
- def inner():
- print(a)
- print(b)
- return inner
-
-
- a = 2
- b = 3
- ret = wrapper(a,b)
-
- #也是闭包
查看这个函数有没有自由变量就行了
- # 函数名.__code__.co_freevars 查看函数的自由变量
- print(avg.__code__.co_freevars) # ('series',)
-
- # 函数名.__code__.co_varnames 查看函数的局部变量
- print(avg.__code__.co_varnames) # ('new_value', 'total')
- # 函数名.__closure__ 获取具体的自由变量对象,也就是cell对象。
- # (<cell at 0x0000020070CB7618: int object at 0x000000005CA08090>,)
- # cell_contents 自由变量具体的值
- print(avg.__closure__[0].cell_contents) # []
上面案例三最难判断是不是闭包,为了进一步确认,用代码判断闭包
- # 例三:
-
- def wrapper(a,b):
- def inner():
- print(a)
- print(b)
- return inner
- a = 2
- b = 3
- ret = wrapper(a,b)
-
- #如何用代码判断闭包?
- print(ret.__code__.co_freevars)
-
- ('a', 'b')
-
- Process finished with exit code 0
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。