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吧! 能接受函数做参数的函数我们称之为高阶函 ...
随机推荐
- jquery、js调用iframe父窗口与子窗口元素的方法整理
1. jquery 在iframe子页面获取父页面元素代码如下: $("#objid", parent.document) 2. jquery在父页面 获取iframe子页面的元素 ...
- SAP中的读访问日志Read Access Logging(RAL)
定义 读取访问日志(以下简称RAL)用于监视并记录对敏感数据的读取访问.这里的数据是指会被法律,外部公司政策或公司内部政策归类为敏感信息的数据.以下典型问题可能会与使用读取访问日志的应用程序有关: 谁 ...
- ubuntu16.04安装jdk1.8
首先去Oracle官网下载JDK1.8的tar.gz压缩包. 然后下载下来的包的默认位置应该是在~/下载/下. 执行如下命令解压缩并安装JDK. cd ~/下载/ tar -zxvf jdk-8u16 ...
- 学习React系列(七)——Fragments、Portals、Error Boundaries与WEB组件
React.Fragment portals Error Boundaries WEB组件 React.Fragment 想象一个场景,想把td包装为组件添加到table中去,代码如下: class ...
- 关于python 使用腾讯云OCR 通用印刷体识别
腾讯的python SDK没有通用印刷体识别,所以参考了别人识别网上图片的方式:https://www.cnblogs.com/semishigure/p/7690789.html 但是咱们使用的基本 ...
- 0307-关于html
html最主要的三点: 1.标签的写法.用法 <标签名 属性名1="属性值1" 属性名2="属性值2">内容</标签名> 比如:< ...
- [LeetCode] Cut Off Trees for Golf Event 为高尔夫赛事砍树
You are asked to cut off trees in a forest for a golf event. The forest is represented as a non-nega ...
- Pycharm节能模式
如题,开启节能模式代码不会自动补全.
- [Luogu 1410]子序列
Description 给定一个长度为N(N为偶数)的序列,问能否将其划分为两个长度为N/2的严格递增子序列, Input 若干行,每行表示一组数据.对于每组数据,首先输入一个整数N,表示序列的长度. ...
- poj 2528 (线段树+离散化)
poj 2528 For each input data set print the number of visible posters after all the posters are place ...