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

简介: 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
相关文章
|
6月前
|
数据安全/隐私保护 Python
Python中装饰器、回调函数、闭包、派生的区别与应用详解
Python中装饰器、回调函数、闭包、派生的区别与应用详解
67 0
|
7月前
|
存储 自然语言处理 Python
Python闭包(Python Closures)介绍
介绍python的闭包语法。
49 0
Python闭包(Python Closures)介绍
|
21天前
|
人工智能 机器人 测试技术
【python】python闭包的详细解读(傻瓜式教学)
【python】python闭包的详细解读(傻瓜式教学)
|
1月前
|
存储 程序员 Python
Python教程第9章 | 通俗易懂学闭包
本文通过一个需求探讨闭包的基本概念与用法,帮助快速理解闭包。
14 0
|
2月前
|
自然语言处理 安全 Python
Python中的闭包和高阶函数详解
Python中的闭包和高阶函数详解
|
2月前
|
Python
在Python中,如何创建和使用闭包?
在Python中,如何创建和使用闭包?
|
2月前
|
自然语言处理 Python
在Python中,什么是闭包?
在Python中,什么是闭包?
|
3月前
|
Python
Python学习 -- 高阶、闭包、回调、偏函数与装饰器探究
Python学习 -- 高阶、闭包、回调、偏函数与装饰器探究
20 0
|
8月前
|
Python
|
4月前
|
Python
Python 基础知识:解释 Python 的装饰器和函数闭包的关系。
Python 基础知识:解释 Python 的装饰器和函数闭包的关系。
25 0