Python 2.7 的闭包中的自由变量(co_freevars)只读的.Python需要某些技巧来"变相修改"自由变量:

  1. >>> def add(n):
  2. freevar=[n]
  3. def closure():
  4. freevar[0]+=1
  5. return freevar[0]
  6. return closure
  7.  
  8. >>> add100=add(100)
  9. >>> add100()
  10. 101
  11. >>> add100()
  12. 102

如果你这样定义,则会出错:

  1. >>> def add(n):
  2. def closure():
  3. n+=1
  4. return n
  5. return closure
  6.  
  7. >>> add100=add(100)
  8. >>> add100()
  9.  
  10. Traceback (most recent call last):
  11. File "<pyshell#15>", line 1, in <module>
  12. add100()
  13. File "<pyshell#13>", line 3, in closure
  14. n+=1
  15. UnboundLocalError: local variable 'n' referenced before assignment
  16. >>>

原因在于Python的数字,字符串是"不可变类型".列表是"可变类型".例如:

  1. >>> a=10
  2. >>> id(a)
  3. 19519444
  4. >>> a=a+3
  5. >>> id(a)
  6. 19519408
  7. >>> a=[]
  8. >>> id(a)
  9. 35054536
  10. >>> a.append(1)
  11. >>> id(a)
  12. 35054536
  13. >>> a
  14. [1]
  15. >>>

而scheme的数字对象就是可变的,而且闭包中的自由变量是可以修改的:

  1. > (define (add n)
  2. (lambda () (set! n (+ 1 n)) n))
  3. > (define add100 (add 100))
  4. > (add100)
  5. 101
  6. > (add100)
  7. 102

其实Python的n+=1有些类似于scheme的 (set! n (+ 1 n)).只不过Python中,n已经指向另外一个新对象了.而sheme,n指向的对象没有发生改变.

更多例证:

  1. (define (add n)
  2. (lambda () (set! n (+ 1 n)) n))
  3.  
  4. (define (addx n)
  5. (lambda () (let ((n 200)) (set! n (+ 1 n)) n)))
  6.  
  7. (define add5 (add 5))
  8. (define addx5 (addx 5))
  9. (add5)
  10. (addx5)
  11. (add5)
  12. (addx5)

结果:

  1. 6
  2. 201
  3. 7
  4. 201
  5. >

又如:

  1. >>> def foo():
  2. m = [3]
  3. def bar(s):
  4. s=m[0]+s
  5. n=2
  6. r=5
  7. def eri():
  8. print 2
  9. for item in dir(bar.func_code):
  10. if isinstance(getattr(bar.func_code,item),tuple):
    print "%s : %s"%(item,getattr(bar.func_code,item))
  11.  
  12. >>> foo()
  13. co_cellvars : ()
  14. co_consts : (None, 0, 2, 5, <code object eri at 01ED8020, file "<pyshell#16>", line 7>)
  15. co_freevars : ('m',)
  16. co_names : ()
  17. co_varnames : ('s', 'n', 'r', 'eri')
  18. >>> def foo():
  19. m = [3]
  20. def bar(s):
  21. s=m[0]+s
  22. n=2
  23. r=5
  24. def eri():
  25. print n
  26. for item in dir(bar.func_code):
  27. if isinstance(getattr(bar.func_code,item),tuple):
    print "%s : %s"%(item,getattr(bar.func_code,item))
  28.  
  29. >>> foo()
  30. co_cellvars : ('n',)
  31. co_consts : (None, 0, 2, 5, <code object eri at 01FE3B18, file "<pyshell#19>", line 7>)
  32. co_freevars : ('m',)
  33. co_names : ()
  34. co_varnames : ('s', 'r', 'eri')
  35. >>>

co_varnames 本地变量

co_freevars 自由变量(闭包体现)

co_cellvars  (被子函数引用的变量,不知叫啥合适)

Python 2.7 闭包的局限的更多相关文章

  1. 说说Python中的闭包 - Closure

    转载自https://segmentfault.com/a/1190000007321972 Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西 ...

  2. 说说Python中的闭包

    Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西. 闭包的概念 我们尝试从概念上去理解一下闭包. 在一些语言中,在函数中可以(嵌套)定义另一个 ...

  3. Python中的闭包 - Closure

    Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西. 闭包的概念 我们尝试从概念上去理解一下闭包. 在一些语言中,在函数中可以(嵌套)定义另一个 ...

  4. 21.python中的闭包和装饰器

    python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure). 以下说明主要针对 python ...

  5. 【转】python中的闭包

    转自:http://www.cnblogs.com/ma6174/archive/2013/04/15/3022548.html python中的闭包 什么是闭包? 简单说,闭包就是根据不同的配置信息 ...

  6. Python 入门之 闭包

    Python 入门之 闭包 1.闭包 (1)在嵌套函数内使用(非本层变量)和非全局变量就是闭包 (2)_ closure _ 判断是不是闭包 def func(): a = 1 def foo(): ...

  7. Python核心编程-闭包

    百度搜了一下闭包的概念:简而言之,闭包的作用就是在外部函数执行完并返回后,闭包使得收机制不会收回函数所占用的资源,因为内部函数的执行需要依赖外函数中的变量.这是对闭包作用的非常直白的描述,不专业也不严 ...

  8. Python深入04 闭包

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 闭包(closure)是函数式编程的重要的语法结构.函数式编程是一种编程范式 (而 ...

  9. 轻松理解python中的闭包和装饰器 (下)

    在 上篇 我们讲了python将函数做为返回值和闭包的概念,下面我们继续讲解函数做参数和装饰器,这个功能相当方便实用,可以极大地简化代码,就让我们go on吧! 能接受函数做参数的函数我们称之为高阶函 ...

随机推荐

  1. $rootscope说明

    scope是AngularJS中的作用域(其实就是存储数据的地方),很类似JavaScript的原型链 .搜索的时候,优先找自己的scope,如果没有找到就沿着作用域链向上搜索,直至到达根作用域roo ...

  2. Unity中的基础光照

    渲染包含了两大部分:决定一个像素的可见性,决定这个像素上的光照计算. 光照模型就是用于决定在一个像素上进行怎样的光照计算. 一.光源 在实时渲染中我们通常把光源当做一个没有体积的点. 1.1 辐照度 ...

  3. 文件上传详解 (HTML FILE)

    FileUpload 对象 在 HTML 文档中 <input type="file"> 标签每出现一次,一个 FileUpload 对象就会被创建. 该元素包含一个文 ...

  4. [NOIp 2016]天天爱跑步

    Description 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图 ...

  5. ●BZOJ 3879 SvT

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3879 题解: 后缀数组,单调栈,RMQ 其实类似 BZOJ 3238 [Ahoi2013]差 ...

  6. hdu 1130 How Many Trees?(Catalan数)

    How Many Trees? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  7. [Codeforces]860E Arkady and a Nobody-men

    屯一个虚树的板子,顺便总结一下这样的题型. Description 给定一棵n个节点的有根树,在输入数据通过给出每个节点的父亲来表示这棵树.若某个节点的父亲为0,那么该节点即为根.现在对于每个点,询问 ...

  8. 浅谈java中内置的观察者模式与动态代理的实现

    一.关于观察者模式 1.将观察者与被观察者分离开来,当被观察者发生变化时,将通知所有观察者,观察者会根据这些变化做出对应的处理. 2.jdk里已经提供对应的Observer接口(观察者接口)与Obse ...

  9. PHP查看本地文件夹及删除文件夹操作

    查看文件夹(包括文件夹内所有的文件夹和文件) function descdir($dir){ if(is_dir($dir)){ if($dh=opendir($dir)){ while(($file ...

  10. 使设备I/O的核心模块工作,有哪两种方式?

    设备处理进程方式.文件操作方式.