Python 2.7 闭包的局限
Python 2.7 的闭包中的自由变量(co_freevars)只读的.Python需要某些技巧来"变相修改"自由变量:
- >>> def add(n):
- freevar=[n]
- def closure():
- freevar[0]+=1
- return freevar[0]
- return closure
- >>> add100=add(100)
- >>> add100()
- 101
- >>> add100()
- 102
如果你这样定义,则会出错:
- >>> def add(n):
- def closure():
- n+=1
- return n
- return closure
- >>> add100=add(100)
- >>> add100()
- Traceback (most recent call last):
- File "<pyshell#15>", line 1, in <module>
- add100()
- File "<pyshell#13>", line 3, in closure
- n+=1
- UnboundLocalError: local variable 'n' referenced before assignment
- >>>
原因在于Python的数字,字符串是"不可变类型".列表是"可变类型".例如:
- >>> a=10
- >>> id(a)
- 19519444
- >>> a=a+3
- >>> id(a)
- 19519408
- >>> a=[]
- >>> id(a)
- 35054536
- >>> a.append(1)
- >>> id(a)
- 35054536
- >>> a
- [1]
- >>>
而scheme的数字对象就是可变的,而且闭包中的自由变量是可以修改的:
- > (define (add n)
- (lambda () (set! n (+ 1 n)) n))
- > (define add100 (add 100))
- > (add100)
- 101
- > (add100)
- 102
其实Python的n+=1有些类似于scheme的 (set! n (+ 1 n)).只不过Python中,n已经指向另外一个新对象了.而sheme,n指向的对象没有发生改变.
更多例证:
- (define (add n)
- (lambda () (set! n (+ 1 n)) n))
- (define (addx n)
- (lambda () (let ((n 200)) (set! n (+ 1 n)) n)))
- (define add5 (add 5))
- (define addx5 (addx 5))
- (add5)
- (addx5)
- (add5)
- (addx5)
结果:
- 6
- 201
- 7
- 201
- >
又如:
- >>> def foo():
- m = [3]
- def bar(s):
- s=m[0]+s
- n=2
- r=5
- def eri():
- print 2
- for item in dir(bar.func_code):
- if isinstance(getattr(bar.func_code,item),tuple):
print "%s : %s"%(item,getattr(bar.func_code,item))- >>> foo()
- co_cellvars : ()
- co_consts : (None, 0, 2, 5, <code object eri at 01ED8020, file "<pyshell#16>", line 7>)
- co_freevars : ('m',)
- co_names : ()
- co_varnames : ('s', 'n', 'r', 'eri')
- >>> def foo():
- m = [3]
- def bar(s):
- s=m[0]+s
- n=2
- r=5
- def eri():
- print n
- for item in dir(bar.func_code):
- if isinstance(getattr(bar.func_code,item),tuple):
print "%s : %s"%(item,getattr(bar.func_code,item))- >>> foo()
- co_cellvars : ('n',)
- co_consts : (None, 0, 2, 5, <code object eri at 01FE3B18, file "<pyshell#19>", line 7>)
- co_freevars : ('m',)
- co_names : ()
- co_varnames : ('s', 'r', 'eri')
- >>>
co_varnames 本地变量
co_freevars 自由变量(闭包体现)
co_cellvars (被子函数引用的变量,不知叫啥合适)
Python 2.7 闭包的局限的更多相关文章
- 说说Python中的闭包 - Closure
转载自https://segmentfault.com/a/1190000007321972 Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西 ...
- 说说Python中的闭包
Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西. 闭包的概念 我们尝试从概念上去理解一下闭包. 在一些语言中,在函数中可以(嵌套)定义另一个 ...
- Python中的闭包 - Closure
Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西. 闭包的概念 我们尝试从概念上去理解一下闭包. 在一些语言中,在函数中可以(嵌套)定义另一个 ...
- 21.python中的闭包和装饰器
python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure). 以下说明主要针对 python ...
- 【转】python中的闭包
转自:http://www.cnblogs.com/ma6174/archive/2013/04/15/3022548.html python中的闭包 什么是闭包? 简单说,闭包就是根据不同的配置信息 ...
- Python 入门之 闭包
Python 入门之 闭包 1.闭包 (1)在嵌套函数内使用(非本层变量)和非全局变量就是闭包 (2)_ closure _ 判断是不是闭包 def func(): a = 1 def foo(): ...
- Python核心编程-闭包
百度搜了一下闭包的概念:简而言之,闭包的作用就是在外部函数执行完并返回后,闭包使得收机制不会收回函数所占用的资源,因为内部函数的执行需要依赖外函数中的变量.这是对闭包作用的非常直白的描述,不专业也不严 ...
- Python深入04 闭包
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 闭包(closure)是函数式编程的重要的语法结构.函数式编程是一种编程范式 (而 ...
- 轻松理解python中的闭包和装饰器 (下)
在 上篇 我们讲了python将函数做为返回值和闭包的概念,下面我们继续讲解函数做参数和装饰器,这个功能相当方便实用,可以极大地简化代码,就让我们go on吧! 能接受函数做参数的函数我们称之为高阶函 ...
随机推荐
- $rootscope说明
scope是AngularJS中的作用域(其实就是存储数据的地方),很类似JavaScript的原型链 .搜索的时候,优先找自己的scope,如果没有找到就沿着作用域链向上搜索,直至到达根作用域roo ...
- Unity中的基础光照
渲染包含了两大部分:决定一个像素的可见性,决定这个像素上的光照计算. 光照模型就是用于决定在一个像素上进行怎样的光照计算. 一.光源 在实时渲染中我们通常把光源当做一个没有体积的点. 1.1 辐照度 ...
- 文件上传详解 (HTML FILE)
FileUpload 对象 在 HTML 文档中 <input type="file"> 标签每出现一次,一个 FileUpload 对象就会被创建. 该元素包含一个文 ...
- [NOIp 2016]天天爱跑步
Description 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图 ...
- ●BZOJ 3879 SvT
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3879 题解: 后缀数组,单调栈,RMQ 其实类似 BZOJ 3238 [Ahoi2013]差 ...
- hdu 1130 How Many Trees?(Catalan数)
How Many Trees? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- [Codeforces]860E Arkady and a Nobody-men
屯一个虚树的板子,顺便总结一下这样的题型. Description 给定一棵n个节点的有根树,在输入数据通过给出每个节点的父亲来表示这棵树.若某个节点的父亲为0,那么该节点即为根.现在对于每个点,询问 ...
- 浅谈java中内置的观察者模式与动态代理的实现
一.关于观察者模式 1.将观察者与被观察者分离开来,当被观察者发生变化时,将通知所有观察者,观察者会根据这些变化做出对应的处理. 2.jdk里已经提供对应的Observer接口(观察者接口)与Obse ...
- PHP查看本地文件夹及删除文件夹操作
查看文件夹(包括文件夹内所有的文件夹和文件) function descdir($dir){ if(is_dir($dir)){ if($dh=opendir($dir)){ while(($file ...
- 使设备I/O的核心模块工作,有哪两种方式?
设备处理进程方式.文件操作方式.