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吧! 能接受函数做参数的函数我们称之为高阶函 ...
随机推荐
- win10 apache配置虚拟主机后localhost无法使用
win10系统配置虚拟主机1.用记事本或Sublime Text打开httpd.confctrl + f 搜索httpd-vhosts.conf 将#Include conf/extra/httpd- ...
- scrapy爬取西刺网站ip
# scrapy爬取西刺网站ip # -*- coding: utf-8 -*- import scrapy from xici.items import XiciItem class Xicispi ...
- Vue项目模板--和--webpack自动化构建工具的---项目打包压缩使用
[首先安装node.js]: 1. 从node.js官网下载并安装node,安装过程很简单. 2. npm 版本需要大于 3.0,如果低于此版本需要升级它: # 查看版本 npm -v2.3.0 #升 ...
- markdown常用语法简记
一级标题 二级标题 三级标题 ..... 无序列表 First Second Third 有序列表 第一条 第二条 第三条 链接 我的github主页 锚点 无序列表 代码块 var vm = new ...
- github git 在GitHub上创建项目并将本地项目push到网站上
众所周知,git是与svn类似的版本控制系统,git的去中心化.分布式等的优点,在不久将来用户量大有可能超过svn, 常见的代码托管网站有GitHub,coding.net, gitee.com 码云 ...
- MySQL-分组查询(GROUP BY)及二次筛选(HAVING)
为了测试GROUP BY 语句,我们创建两张表,并往表中添加数据 -- 创建部门表 CREATE TABLE IF NOT EXISTS department( id TINYINT UNSIGNED ...
- mybatis学习三
Mybatis与pageHelper分页: 分页分为假分页和真分页对应的专业术语叫做逻辑分页和物理分页 逻辑分页:将所有的数据从数据库查询出来,根据需求截取符合要求的数据返回,方便统一但效 ...
- 迎圣诞,拿大奖活动赛题_SQLi(sprintf格式化字符)
看题目应该就是注入没跑了 先拿正常输入试试,输了admin,admin,结果返回password error!,说明还真的存在admin账户 拿常规注入语句试探一下admin' and 1=1%23, ...
- codevs 搜索题汇总(黄金级)
2801 LOL-盖伦的蹲草计划 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题目描述 Description 众所周知,LOL这款伟大的游戏,有个叫盖 ...
- bzoj 3244: [Noi2013]树的计数
Description 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的BFS序也有可能相同, ...