什么是闭包

其实,闭包指延伸了作用域的函数,其中包含函数定义体中引用、但是
不在定义体中定义的非全局变量。函数是不是匿名的没有关系,关键是
它能访问定义体之外定义的非全局变量。

示例 7-8 average_oo.py:计算移动平均值的类

class Averager():
def __init__(self):
self.series = []
def __call__(self, new_value):
self.series.append(new_value)
total = sum(self.series)
return total/len(self.series)

示例 7-9 是函数式实现,使用高阶函数 make_averager。

def make_averager():
series = []
def averager(new_value):
series.append(new_value)
total = sum(series)
return total/len(series)
return averager

注意,这两个示例有共通之处:调用 Averager() 或
make_averager() 得到一个可调用对象 avg,它会更新历史值,然后
计算当前均值。在示例 7-8 中,avg 是 Averager 的实例;在示例 7-9
中是内部函数 averager。不管怎样,我们都只需调用 avg(n),把 n
放入系列值中,然后重新计算均值。
Averager 类的实例 avg 在哪里存储历史值很明显:self.series 实例
属性。但是第二个示例中的 avg 函数在哪里寻找 series 呢?
注意,series 是 make_averager 函数的局部变量,因为那个函数的定
义体中初始化了 series:series = []。可是,调用 avg(10)
时,make_averager 函数已经返回了,而它的本地作用域也一去不复
返了。
在 averager 函数中,series 是自由变量(free variable)。这是一个
技术术语,指未在本地作用域中绑定的变量,参见图 7-1。

图 7-1:averager 的闭包延伸到那个函数的作用域之外,包含自由
变量 series 的绑定
审查返回的 averager 对象,我们发现 Python 在 __code__ 属性(表示
编译后的函数定义体)中保存局部变量和自由变量的名称,如示例 7-11所示。

综上,闭包是一种函数,它会保留定义函数时存在的自由变量的绑定,
这样调用函数时,虽然定义作用域不可用了,但是仍能使用那些绑定。
注意,只有嵌套在其他函数中的函数才可能需要处理不在全局作用域中
的外部变量。

闭包(流畅的python 学习笔记)的更多相关文章

  1. 流畅的python学习笔记第七章:装饰器

    装饰器就如名字一样,对某样事物进行装饰过后然后返回一个新的事物.就好比一个毛坯房,经过装修后,变成了精装房,但是房子还是同样的房子,但是模样变了. 我们首先来看一个函数.加入我要求出函数的运行时间.一 ...

  2. 流畅的python学习笔记:第三章

    字典的变种: OrderedDict 首先来看下面的代码,在一个字典中,有name,age,city,在遍历这个字典的时候.顺序却是随机的,不是按照我们添加的顺序也就是name->age-> ...

  3. 流畅的python学习笔记:第二章

    第二章开始介绍了列表这种数据结构,这个在python是经常用到的结构 列表的推导,将一个字符串编程一个列表,有下面的2种方法.其中第二种方法更简洁.可读性也比第一种要好 str='abc' strin ...

  4. 流畅的python学习笔记:第一章

    这一章中作者简要的介绍了python数据模型,主要是python的一些特殊方法.比如__len__, __getitem__. 并用一个纸牌的程序来讲解了这些方法 首先介绍下Tuple和nametup ...

  5. 流畅的python学习笔记:第五章

    在python中一切都可以视作为对象,包括函数.我们来看个例子: def function_try():     '''it is funciton try doc'''     print 'fun ...

  6. 流畅的python学习笔记:第九章:符合python风格的对象

    首先来看下对象的表现形式: class People():     def __init__(self,name,age):         self.name=name         self.a ...

  7. 流畅的python学习笔记第八章:深拷贝,浅拷贝,可变参数

    首先来看赋值,浅拷贝,深拷贝. 一赋值: a=['word',2,3] b=a print id(a),id(b) print [id(x) for x in a] print [id(x) for ...

  8. 流畅的python学习笔记:第十三章:重载运算符__add__,__iadd__,__radd__,__mul__,__rmul__,__neg__,__eq__,__invert__,__pos__

    在前面第十章以及第一章的时候介绍了Vector对象的运算符重载.第十三章专门介绍运算符重载.这里我们看几个之前没讲过的运算符__neg__,__pos__,__invert__ class Vecto ...

  9. 流畅的python学习笔记:第十一章:抽象基类

    __getitem__实现可迭代对象.要将一个对象变成一个可迭代的对象,通常都要实现__iter__.但是如果没有__iter__的话,实现了__getitem__也可以实现迭代.我们还是用第一章扑克 ...

随机推荐

  1. 二分查找c++简单模板

    //数组a[]中有n各元素,已经按升序排序,待查找的元素x sort(a,a+n); //升序排序 template<class Type> int BinarySearch(Type a ...

  2. hdu_2444The Accomodation of Students(二分图的判定和计算)

    hdu_2444The Accomodation of Students(二分图的判定和计算) 标签:二分图匹配 题目链接 题意: 问学生是否能分成两部分,每一部分的人都不相认识,如果能分成的话,两两 ...

  3. 微信小程序模板消息详解

    先放代码 wxml: <form name='pushMsgFm' report-submit bindsubmit='orderSign'> <view> 单号: 0< ...

  4. 使用setTimeout实现setInterval

    setInterval = () =>{ console.log(1) //使用递归 setTimeout(setInterval,1000); }; setInterval()

  5. oracle游标的使用

    --游标的使用 步骤1.声明游标 .打开游标 .获取数据 .关闭游标 declare cursor cur is select * from emp; t_sal cur%rowtype; begin ...

  6. iOS微信自动抢红包插件(支持后台和锁屏下抢红包)

    前言:本文主要讲述使用hook方式实现红包插件,涉及到tweak相关知识,如果你不想了解具体实现细节可直接到我的Github地址参考安装(包含越狱和非越狱两种方法)   转眼间2017即将过去,又到了 ...

  7. No input file specified的解决方法apache伪静态

    http://jingyan.baidu.com/article/dca1fa6f8d623ff1a44052e8.html (一)IIS Noinput file specified 方法一:改PH ...

  8. iis配置完成,出现HTTP 错误 403.14 - Forbidden

    版权声明:本文为博主原创文章,未经博主允许不得转载.转载请标明文章出处和原文链接. 403.14 禁止访问:在 Web 服务器上已拒绝目录列表 解决方案一:一般情况站点都是不会允许直接读取目录内容的, ...

  9. xmind2013激活

    参考链接:http://blog.163.com/m15999573195_1/blog/static/248705063201542622112823/

  10. Vue.js的坑

    参考网址:http://cn.vuejs.org/v2/guide/components.html 1.camelCase vs. kebab-case HTML 特性不区分大小写.当使用非字符串模版 ...