Python-关于Python中闭包的一些理解

看不懂的定义:闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境)。

既然是看不懂的定义,真看不懂上面定义的话就忽略吧。

在python中,函数可以作为另一个函数的参数或返回值,可以赋给一个变量。函数可以嵌套定义,即在一个函数内部可以定义另一个函数,有了嵌套函数这种结构,便会产生闭包问题。

好理解一点的定义:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)

举个栗子:


1

2

3

4


def outer(x):

def inner(y):

return x + y

return inner

结合代码分析定义:

如果在一个内部函数里 — inner()就是内部函数。

对在外部作用域(但不是在全局作用域)的变量进行引用 — x就是被引用的变量,x在外部作用域,但不在全局作用域。

那么内部函数就被认为是闭包 —- inner就是一个闭包。

如果你想学习Python可以来这个群,首先是四七二,中间是三零九,最后是二六一,里面有大量的学习资料可以下载。

关于闭包很难理解的一个问题,我尝试用图形化思维来理解

先看一个简单的循环


1

2


for i in range(3):

print i

在程序里面经常会出现这类的循环语句,python的一个现象是,当循环结束以后,循环体中的临时变量i不会销毁,而是继续存在于执行环境中。还有一个python的现象是,python的函数只有在执行时,才会去找函数体里的变量的值。

这段话特别需要记住两点:

  1. 当循环结束时,循环体中的临时变量i不会销毁
  2. python的函数只有在执行时,才会去找函数体里的变量的值

记住上面两点后,下面看经典的难理解的栗子:


1

2

3

4

5

6

7

8

9


def foo():

func_list = []

for i in range(3):

def inner():

return i*i

func_list.append(inner)

return func_list

f = foo()

在这个例子中,每次循环都创建一个新的函数,并且将创建的三个函数对象都添加到func_list这个列表中

f = foo()这里调用foo(),f中就保存了一个列表对象,这个列表中保存了3个函数对象。

不妨打印一下看看 f 中三个元素的值:


1

2

3

4


>>> print f[0],'\n',f[1],'\n',f[2]

<function inner at 0x000000000263BAC8>

<function inner at 0x0000000002E664A8>

<function inner at 0x0000000002E66518>

从打印信息可以看出,f 中存放了3个函数名相同,但内存地址不同,的函数对象。

此时调用一下三个函数


1

2

3

4

5

6


>>> f[0]()

4

>>> f[1]()

4

>>> f[2]()

4

可能有些人认为这段代码的执行结果应该是0,1,4.但是实际的结果是4,4,4。这是因为当把函数对象加入func_list列表里时,python还没有给i赋值,只有当执行时,再去找i的值是什么,这时在第一个for循环结束以后,i的值是2,所以以上代码的执行结果是4,4,4.

不好理解的话,画个流程图(点击图片查看大图):

这里也可以直观的理解文章开始提到的闭包的定义公式(闭包=函数+引用环境)

结果全部都是 4,原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数被调用时,它们所引用的变量i已经变成了2,因此最终结果为4。

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

如果要正确的输出引用循环变量后的值,只需要将每次循环变量锁定到闭包中,具体实现如下:


1

2

3

4

5

6

7

8

9


def foo():

func_list = []

for i in range(3):

def inner( x = i):

print x*x

func_list.append(inner)

return func_list

f = foo()

这样的话,打印调用每个闭包后的结果为 0 , 1, 4 


1

2

3

4

5

6


>>> f[0]()

0

>>> f[1]()

1

>>> f[2]()

4

时间: 2024-10-21 08:40:43

Python-关于Python中闭包的一些理解的相关文章

可爱的Python:Python中的函数编程(一)

尽管用户通常将 Python 看作是一个过程性和面向对象语言,但它实际上包含了实现完整函数编程所需的每样事物.本文讨论了函数编程的常规概念,并说明了在 Python 中实现函数技术的方法. 我们最好从最难的问题开始:"到底什么是函数编程 (FP)?"一个答案可能会说 FP 就是您在使用例如 Lisp.Scheme.Haskell.ML.OCAML.Clean.Mercury.Erlang(或其它一些)语言进行编程时所做的.这是一个稳妥的答案,但不能很确切地阐明问题.不幸的是,即使是函数

python 八皇后中的列表问题

问题描述 python 八皇后中的列表问题 我这里写了一个简单的八皇后程序,用的是最笨的算法,大家就不要吐槽我的算法了,问题是我的保存所有解法的总列表不正常,列表中所有元素都一样,劳烦大家看下问题出在哪 import time import os def check(list_): #这个函数用来检查当前位置是否合法 for i in range(0,len(list_)-1): if len(list_)==1 : continue for j in range(i+1,len(list_))

Python网络编程中urllib2模块的用法总结_python

一.最基础的应用 import urllib2 url = r'http://www.baidu.com' html = urllib2.urlopen(url).read() print html 客户端与服务器端通过request与response来沟通,客户端先向服务端发送request,然后接收服务端返回的response urllib2提供了request的类,可以让用户在发送请求前先构造一个request的对象,然后通过urllib2.urlopen方法来发送请求 import ur

python小程序中number = numbers[position]

问题描述 python小程序中number = numbers[position] number = numbers[position] #请问这一行应该怎么理解呢? 解决方案 position的值依次加一,number的值每次去列表中对一的值. 解决方案二: 还是不太明白 while会运行3次是吧,这三次number会得到什么值呢? 解决方案三: number就是获取numbers数组中的各个元素的值,你可以看看position的各个值 解决方案四: 谢谢, 但如果number只是获取列表中的

python scrapy框架中from_crawler的问题

问题描述 python scrapy框架中from_crawler的问题 from_crawler这个方法有什么作用,文档没翻译明白,我在一些例子中,几乎每个类里都有 @calssmethod 的from_crawler方法 和 from_settings方法,个人理解应该是一个初始化crawler的方法 ,我想知道他是在框架的哪里,什么时候调用的,不写这个方法而在__init__里初始化又有什么区别?初学新手被困扰了很久,看了几天就是没完全理解,,不弄明白感觉看其他地方就特别不顺,希望得到指教

Python检测字符串中是否包含某字符集合中的字符

  这篇文章主要介绍了Python检测字符串中是否包含某字符集合中的字符,需要的朋友可以参考下 目的 检测字符串中是否包含某字符集合中的字符 方法 最简洁的方法如下,清晰,通用,快速,适用于任何序列和容器 代码如下: def containAny(seq,aset): for c in seq: if c in aset: return True return False 第二种适用itertools模块来可以提高一点性能,本质上与前者是同种方法(不过此方法违背了Python的核心观点:简洁,清

python过滤字符串中不属于指定集合中字符的类实例

  本文实例讲述了python过滤字符串中不属于指定集合中字符的类.分享给大家供大家参考.具体如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # -*- coding: utf-8 -*- import sets class Keeper(object): def __init__(self, keep): self.keep = sets.Set(map(ord, keep)) def __getitem__(self, n): if n

js中的闭包之我理解

闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样. 但是他也是js能力提升中无法绕过的一环,几乎每次面试必问的问题,因为在回答的时候.你的答案的深度,对术语的理解以及js内部解释器的运作 方式的描述,都是可以看出你js实际水平的.即使你没答对,也能让考官对你的水平有个评估.那么我先来说说我对js中的闭包的理解. 闭包是很多语言都具备的特性,在js中,闭包主要涉及到js的几个其他的特性:作用域链,垃圾(内存)回收机制,函数嵌套,等等. 在理解闭包以前.最好

可爱的Python:Python中的文本处理

与其它几种流行的脚本语言一样,Python 是一种用于浏览和处理文本数据的优秀工具.本文为 Python 的初学者概述了 Python 的文本处理工具.文章说明了规则表达式的一些常规概念,并提供了处理文本时,什么情况下应使用(或不使用)规则表达式的建议. 什么是 Python? Python 是由 Guido van Rossum 开发的.可免费获得的.非常高级的解释型语言.其语法简单易懂,而其面向对象的语义功能强大(但又灵活).Python 可以广泛使用并具有高度的可移植性. 字符串 -- 不