python闭包与引用以及需要注意的陷阱


Posted in Python onSeptember 18, 2020

python闭包

关于闭包, 很多blog中都这样解释 :对于一个嵌套定义的函数,外层的函数的返回值是内层函数,而在内层函数中又引用了外层函数的局部变量,在外层函数执行后,其局部变量并非被回收,而会同返回的内层函数一同存在,而这一现象被称为闭包(closure)。

不过以上的理解有些繁琐和局限, 在计算机科学中 ,闭包(Closure)词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。 这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。 也即对于第一段中的定义可以适当放开一些限制条件,python中的闭包实现也并非那么局限。

引用

通过上文介绍可以对于python闭包有大概的了解, 但是有些看似简单的细节却需要进一步阐述 。

python中变量的概念,这是与C/C++中极为不同的,在C/C++中变量是一个名称与内存合一的实体,改变一个变量的值,并不改变其内存的地址。 而变量这个概念在python中并不合用,很多场合它的运用都会让人混淆 。

python中所使用的概念是引用和对象,即如a=123,a即是一个引用名称,123是内存中所储存的对象值。这其实更像是C/C++中的指针与其所指向的内存,可以看作python在此之上对语法进行了包装。

回到之前讨论的闭包话题,在其中用到了 变量 的概念,即函数引用的 变量 将与函数一同存在,这里的 变量 其实是引用名称与内存对象的复合概念。我们这里对其进行进一步的阐明:

函数中所使用的外层函数引用名称(指针),在外层函数退出后其所指向的内存对象并不回收,而该引用名称(指针)会与内层函数一同存在,虽然此时该引用名称(指针)对于内层函数不是“可见的”。

陷阱

def count(): 
  fs = [] 
  for i in range(1, 4): 
    def f(): 
      return j*j 
    fs.append(f)
  return fs

f1, f2, f3 = count()
print(f1())
print(f2())
print(f3())

对于以上代码,假如按照C/C++中的概念去理解python中的变量,就会以为其输出依次为1、2、3。其实不然,真正输出为:3、3、3。根据上一小节中对于python中引用与闭包的阐述,在内存f函数中使用外层的引用名称i,在循环中虽然将不同的f函数加入到列表fs中,但是它们都使用的是同一个引用i,而该引用最后对应的值为3。

再看一段代码,这个会稍微复杂一点

def test():
  for i in range(4):
    yield i
    
g=test()

for n in [1,10]:
  g=(n+i for i in g)
  
print(list(g))

上面这段代码的输出,一时不查之下也会以为是11、12、13、14,而其真实结果却是20、21、22、23,让人一时抓不到头脑。首先在for循环中的生成器表达式(n+i for i in g),它其实本质上是一个函数,写成表达式的形式不过是一种语法糖,其函数形式为:

def gen(n):
  # g是外面全局的那个生成器g
  for i in g:
    yield n+i

即生成器generator本身是一种算法或是函数,只有在“调用”它的时候,也就是对其进行for或是list或是next之类的操作时,才会真正的有值流动。

那么对于以上第二例子中的代码,在for循环内n=1时,g这个生成器被重新赋值,但注意它此时只是一个特殊的函数,此时的n与i并没有真正相加,在for循环的第二轮n=10的时候,(n+i for i in g)表达式中对g才进行了调用,那么此时流进函数的n值其实是10,也就是此时g这个生成器对应的值为10、11、12、13,也就是i所引用的是这些值,下面又以相同的n+i的形式创造一个新的生成器对g重新赋值,并退出循环。则自然,此时g中对应的值为20、21、22、23.

以上就是python闭包与引用以及需要注意的陷阱的详细内容,更多关于python 闭包与引用的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python UnicodeEncodeError: 'gbk' codec can't encode character 解决方法
Apr 24 Python
Python实现简单的HttpServer服务器示例
Sep 25 Python
详解Python核心编程中的浅拷贝与深拷贝
Jan 07 Python
python和shell获取文本内容的方法
Jun 05 Python
python抖音表白程序源代码
Apr 07 Python
Python爬取腾讯视频评论的思路详解
Dec 19 Python
python如何使用Redis构建分布式锁
Jan 16 Python
Python龙贝格法求积分实例
Feb 29 Python
Python实现UDP程序通信过程图解
May 15 Python
Python代码注释规范代码实例解析
Aug 14 Python
Python实现给PDF添加水印的方法
Jan 25 Python
学点简单的Django之第一个Django程序的实现
Feb 24 Python
python 代码运行时间获取方式详解
Sep 18 #Python
python判断字符串以什么结尾的实例方法
Sep 18 #Python
python绘制趋势图的示例
Sep 17 #Python
Python绘制组合图的示例
Sep 18 #Python
记一次Django响应超慢的解决过程
Sep 17 #Python
Visual Studio Code搭建django项目的方法步骤
Sep 17 #Python
Windows下pycharm安装第三方库失败(通用解决方案)
Sep 17 #Python
You might like
PHP递归算法的详细示例分析
2013/02/19 PHP
PHP 正则判断中文UTF-8或GBK的思路及具体实现
2013/11/26 PHP
php setcookie函数的参数说明及其用法
2014/04/20 PHP
javascript 写类方式之一
2009/07/05 Javascript
JS获取下拉列表所选中的TEXT和Value的实现代码
2014/01/11 Javascript
js控制iframe的高度/宽度让其自适应内容
2014/04/09 Javascript
javascript面向对象之访问对象属性的两种方式分析
2015/01/13 Javascript
JavaScript实现俄罗斯方块游戏过程分析及源码分享
2015/03/23 Javascript
Angularjs制作简单的路由功能demo
2015/04/14 Javascript
JavaScript实现网站访问次数统计代码
2015/08/12 Javascript
jquery中实现时间戳与日期相互转换
2016/04/12 Javascript
JS组件系列之使用HTML标签的data属性初始化JS组件
2016/09/14 Javascript
JavaScript 链式结构序列化详解
2016/09/30 Javascript
解决Vue使用mint-ui loadmore实现上拉加载与下拉刷新出现一个页面使用多个上拉加载后冲突问题
2017/11/07 Javascript
jquery学习笔记之无new构建详解
2017/12/07 jQuery
微信小程序实现animation动画
2018/01/26 Javascript
详解微信小程序之scroll-view的flex布局问题
2019/01/16 Javascript
JS基于ES6新特性async await进行异步处理操作示例
2019/02/02 Javascript
详解Vue中使用Axios拦截器
2019/04/22 Javascript
layui+SSM的数据表的增删改实例(利用弹框添加、修改)
2019/09/27 Javascript
Python读写txt文本文件的操作方法全解析
2016/06/26 Python
对python中UDP,socket的使用详解
2019/08/22 Python
关于Pytorch的MNIST数据集的预处理详解
2020/01/10 Python
什么是Python包的循环导入
2020/09/08 Python
一款利用css3的鼠标经过动画显示详情特效的实例教程
2014/12/29 HTML / CSS
Ray-Ban雷朋奥地利官网:全球领先的太阳眼镜品牌
2020/10/12 全球购物
药学专业大学生个人的自我评价
2013/11/04 职场文书
2014年社区重阳节活动策划方案
2014/09/16 职场文书
2015年爱国卫生工作总结
2015/04/22 职场文书
2015年学校教研室主任工作总结
2015/07/20 职场文书
2015年物业公司保洁工作总结
2015/10/22 职场文书
评奖评优个人先进事迹材料
2015/11/04 职场文书
运动会主持人开幕词
2016/03/04 职场文书
python requests模块的使用示例
2021/04/07 Python
python实现Nao机器人的单目测距
2021/09/04 Python
Python写情书? 10行代码展示如何把情书写在她的照片里
2022/04/21 Python