Python闭包详解,你了解多少?

发布时间:2023年12月28日

大家好,我是kelly,今天给大家分享Python闭包。

一、认识闭包

1、感性上认识

先运行下面的这段代码

从上图可知,Python闭包是一个嵌套函数,这个嵌套函数定义在一个外部函数内部,可以访问外部函数的变量。

闭包一旦创建,外部函数的变量会绑定在闭包上,即使外部函数运行结束后,外部函数的变量依然存在,闭包始终可以访问(甚至修改)。

2、定义上认识

维基百科对闭包的描述:

“1、在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是在支持头等函数的编程语言中实现词法绑定的一种技术。闭包在实现上是一个结构体,它存储了一个函数(通常是其入口地址)和一个关联的环境(相当于一个符号查找表)。

2、闭包跟函数最大的不同在于,当捕捉闭包的时候,它的自由变量会在捕捉时被确定,这样即便脱离了捕捉时的上下文,它也能照常运行。

3、闭包可以用来在一个函数与一组“私有”变量之间建立关联关系。在给定函数被多次调用的过程中,这些私有变量能够保持其持久性。变量的作用域仅限于包含它们的函数,因此无法从其它程序代码部分进行访问。不过,变量的生存期是可以很长,在一次函数调用期间所建立所生成的值在下次函数调用时仍然存在。正因为这一特点,闭包可以用来完成信息隐藏,并进而应用于需要状态表达的某些编程范型中。”

专业点的描述:闭包,英文名词closure,是一个函数以及其捆绑的周边环境状态的引用组合。

因此,闭包和普通函数的区别在于,

(1)闭包捆绑了外部函数的变量

(2)拓展了外部函数的变量的作用域,将外部函数的变量缓存在内存中,其生存期不再受到外部函数的限制。

二、闭包怎么使用

1、闭包怎么使用

举例:以机器学习中的线性回归为例,已知2个参数的权重和截距,求输入具体参数值时的回归值。

这个案例展示了外部函数如何给闭包提供了属性,对于这种用法,实际上通过Python类也能实现。

等价的Python类实现逻辑为:

可见,使用Python类方式的代码量增加了,逻辑更加清晰。此外,如果存在大量属性,建议优先使用Python类,逻辑更清晰。

进一步说明:对于闭包的外层函数中的变量,会一直缓存在内存中,直到程序运行结束。

2、在闭包内怎么修改外部函数变量的值

直接修改是否可行?

很明显,在闭包中直接修改外部变量变量行不通,原因是:

(1)Python变量的作用域优先级为:当前局部作用域变量>外层作用域变量>当前模块中的全局变量>python内置变量。

(2)+=是一个赋值运算,计算结果赋值给inner_func局部作用域的x_base;而在inner_func内部,x_base实际上还不存在,执行+=运算时又无法引用外部函数的x_base。

怎么解决?

使用nonlocal关键字声明,声明闭包中所引用的实际为外部函数中的变量。

说明:与nonlocal关键字对应的是global关键字,global关键字用于声明局部作用域内的变量实际为全局变量,声明后可以读取和修改全局变量。

三、闭包的使用场景、注意点

优点:

(1)避免使用全局变量带来的污染

(2)变量隐藏,对闭包的外层函数的变量进行缓存(通过闭包的__closurre__属性取值可知),对外层函数之外的作用域不可见。

注意点:

(1)闭包所引用外层函数变量带来的内存泄露、内存消耗等问题

四、判断函数是不是闭包

1、根据闭包的定义,人工判断的依据是2点:

(1)是不是嵌套函数(内部函数)

(2)有没有访问外部函数的变量

2、判断函数的__closure__属性,判断取值是否包含ceil对象。

变量a指向inner_func函数,由于outer_func有2个参数:wieght和intercept,因此,inner_func函数作为闭包,属性__closure__包含2个元组,元组cell对象的cell_content属性分别取值100和10。

本文原创,原始版本发表链接:

https://mp.weixin.qq.com/s?__biz=MzI2Mjg3NTY5MQ==&mid=2247484458&idx=1&sn=900ebb9560bae673fb07d25996bcade6&chksm=ea453b6edd32b278c0f5ddc1411a6674252fd5bfe3452d4659f24f90a48de27346aa0ee5a66b#rd

kelly会在公众号「kelly学技术」不定期更新文章,感兴趣的朋友可以关注一下,期待与您交流。

--over--

文章来源:https://blog.csdn.net/qm5132/article/details/135260682
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。