`
384444165
  • 浏览: 255062 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

python闭包中变量引用分析

阅读更多

标题看起来很虎人,其实不敢称为分析。自己这方面仍有欠缺,以前也许还行,现在专门研究语言的时间和精力没那么多了。有解释的不对的地方欢迎各位来板砖,别误导了大众。

 

还是直接说这次的问题,今天@neiddy(javaeye)跟我说起闭包的问题,看那几个例子好有意思,想搞懂的冲动。关于python闭包的问题如果不了解的话,这篇文章还是很不错的:

http://blog.csdn.net/marty_fu/article/details/7679297

问题也源于文中提到的例子。

 

看两段代码:

 

>>> def foo():
       a = 1
       def bar():
              a = a +1
              return a
       return bar()
 
>>> foo()
Traceback (most recent call last):
  File "<pyshell#73>", line 1, in <module>
    foo()
  File "<pyshell#72>", line 6, in foo
    return bar()
  File "<pyshell#72>", line 4, in bar
    a = a +1
UnboundLocalError: local variable 'a' referenced before assignment

 

>>> def foo():
       a = [1]
       def bar():
              a[0] = a[0] + 1
              return a[0]
       return bar()
 
>>> foo()2

  

通过闭包体验函数式编程,还是不错的感觉。原文下面少了括号,不然返回函数本身就没意思了。再说这个神奇的现象,文中只是说改成容器就ok了,为什么呢?

Google了一些内存管理内存分配的东西,都没有找到出路,走投无路只能投奔源码了。从没看过直接看效率太低,幸好有人总结过了,推荐一下”雨痕 Q.yuhen”的《深入Python编程》,实属低调的大神。

直接闭包部分的代码分析雨痕在闭包的一节有讲到,但是没有专门说这个奇怪的问题的机制。

重复的看书吧,参照了书中的’参数’和’闭包’两节,下面说说根据他的讲解和附上的源码,谈谈我的理解。

雨痕在章节的最后提到”CPython实现闭包的原理并不复杂,说白了就是将所引用的外层对象附加到每次都重新创建的内层函数对象身上 (func_closure)。”

这句话是对前面的概括,同时也包含了重要的信息,就是内部函数对应的对象访问外层函数中的变量其实是通过将外层的变量引用到内存对象的堆栈中来访问的,C语言的代码中时按值传递的。

比如第一段代码中的a,其实是引用了1过来,本身的co_nlocals是1,即一个局部变量是等号前面的a(这样说不太对,只是希望帮助理解这个问题)。既然是局部变量a,a = a +1必然是要抛出UnboundLocalError的。

而对于第二个问题,虽然存在一样的情况,但是即便按值传递,数组中每个位置的指针指向的具体是不变的,还是会修改指定位置的值,因此如果是容器型对象就是可行的。

 

痛恨自己的就是这个地方总感觉自己说不清楚,其实就是刚学c语言的时候常玩的指针类游戏,虽然说的很烂,但希望指到要害了。接下来就很简单了,按照这个思路来验证一段代码,也就是如果只是输出这个值,不设定局部变量的话那么应该是可以运行的。

 

>>> def foo():
       a = 1
       def bar():
              return a
       return bar()
 
>>> foo()
1

 

事情果然跟预想的一样发生了。再细细的体会,好好看看雨痕带着分析的代码吧。了解机制走的更远。Python越来越有意思了,用python的思想写代码,益处良多啊。

 

By the way,顺带

>>> flist = []
>>> for i in range(3):
       def foo(x): print x + i
       flist.append(foo)
 
>>> for f in flist:
       f(2)
 
4
4
4

 

 

文中提到这段代码是因为i不被销毁导致的,今天搜内存分配的时候也看到这个东西。编程的时候应该尽量使用list comprehension减少for和while,一是函数化编程简洁明了,另一方面是性能提升和节省一个计数器。

0
0
分享到:
评论

相关推荐

    Python 闭包,函数分隔作用域,nonlocal声明非局部变量操作示例

    本文实例讲述了Python 闭包,函数分隔作用域,nonlocal声明非局部变量操作。分享给大家供大家参考,具体如下: 实例对象也可以实现闭包的功能,不过实例对象消耗的资源(内存)比闭包多。 demo.py(闭包): # 闭包,...

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

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

    对Python闭包与延迟绑定的方法详解

    Python闭包可能会在面试或者是工作中经常碰到,而提到Python的延迟绑定,肯定就离不开闭包的理解,今天总结下 关于闭包的概念以及一个延迟绑定的面试题。 Python闭包 1、什么是闭包,闭包必须满足以下3个条件: 必须...

    基于Python闭包及其作用域详解

    关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记 如果在一个内部函数里,对一个外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被称为闭包...

    python闭包.html

    什么是闭包?如何设置闭包?创建闭包可以用来干什么?闭包的好处,如何正确使用闭包?通过闭包能创建一些只有当前函数能访问的变量,

    Python闭包函数定义与用法分析

    本文实例分析了Python闭包函数定义与用法。分享给大家供大家参考,具体如下: python的闭包 首先python闭包的作用,一个是自带作用域,另一个是延迟计算。 闭包是装饰器的基础。 闭包的基本形式: def 外部函数名()...

    Python中的闭包总结

    在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由...

    Python闭包实现计数器的方法

    本文实例讲述了Python闭包实现计数器的方法。分享给大家供大家参考。具体实现方法如下: 先来看看专业的解释:闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将...

    Python闭包的两个注意事项(推荐)

    什么是闭包? 简单说,闭包就是根据不同的配置信息得到不同...Python闭包函数所引用的外部自由变量是延迟绑定的。 Python In [2]: def multipliers(): ...: return [lambda x: i * x for i in range(4)] In [3]: print

    Python 闭包的使用方法

    在Python中,这些非局部变量只能在默认情况下读取,我们必须将它们显式地声明为非局部变量(使用nonlocal关键字)才能进行修改。 以下是访问非局部变量的嵌套函数的示例。 def print_msg(msg): # This is the outer ...

    Python、Javascript中的闭包比较

    同为脚本语言,python和Javascript具有相似的变量作用域,不像php,函数的内部的所有变量和外部都是隔绝的,也就是说,函数要想处理其外部的数据,必须使用参数把需要处理的数据传递进来(使用global关键词这里不...

    Python高级特性之闭包与装饰器实例详解

    本文实例讲述了Python高级特性之闭包与装饰器。分享给大家供大家参考,具体如下: 闭包 1.函数参数: (1)函数名存放的是函数的地址 (2)函数名()存放的是函数内的代码 (3)函数名只是函数代码空间的引用,当函数名...

    Python学习之路——函数的闭包与装饰器

    在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不...

    Python闭包装饰器使用方法汇总

    对全局函数进行修改:在函数当中加global,在闭包中外边中的变量加nonlocal 闭包定义:有两个函数嵌套使用,里面的函数可以使用外面函数所传输的参数,最后可传递的是里面函数的结构与数据(个人理解)。 最后闭包可以...

    Python新手如何进行闭包时绑定变量操作

    搞不清楚在闭包(closures)中Python是怎样绑定变量的 看这个例子: &gt;&gt;&gt; def create_multipliers(): ... return [lambda x : i * x for i in range(5)] &gt;&gt;&gt; for multiplier in create_multipliers(): ... print ...

    详解 Python中LEGB和闭包及装饰器

    1.Closure:内部函数中对enclosing作用域变量的引用 2.函数实质与属性 函数是一个对象 函数执行完成后内部变量回收 函数属性 函数返回值 passline = 60 def func(val): if val &gt;= passline: print ('pass')...

    Python语言基础:作用域.pptx

    Python 中,变量的访问权限决定于这个变量是在哪里赋值的。变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有4种,分别是:L(Local):最内层,包含局部变量,比如一个函数/方法...

    Python中闭包的用法

    闭包 闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数块+引用...我们注意到一个问题:内嵌函数 inner 中引用到外层函数中的局部变量num,Python解释器会这么处理这个问题呢? 先让我们来看看这段代码的

    实例讲解Python的函数闭包使用中应注意的问题

    里我们来以实例讲解Python的函数闭包使用中应注意的问题,主要针对闭包后新生成的变量来不及初始化而导致找不到变量的错误出现,需要的朋友可以参考下

Global site tag (gtag.js) - Google Analytics