python 函数闭包,python闭包的条件
本文主要介绍Python函数中闭包和延迟绑定的细节。文章围绕主题,详细介绍了细节,具有一定的参考价值。有需要的朋友可以参考一下。
闭包必须满足以下3个条件:
必须有嵌入的函数。嵌入式函数必须应用外部函数的变量。外部函数的返回值必须是嵌入式函数关于请看下面代码:.
定义乘数():
return[lambda x : I * x for I in range(4)]
print([m(2)for m in multipliers()])
[6, 6, 6, 6]
为什么输出结果是[6,6,6,6]?这段代码相当于
定义乘数():
funcs=[]
对于范围(4):中的I
定义栏(x):
返回x*i
函数追加(条形)
返回函数
print([m(2)for m in multipliers()])
[6, 6, 6, 6]
当代码运行时,解释器遇到一个列表解析,并在一个循环中从multipliers()函数获取值,而multipliers()函数返回一个包含四个元素的列表对象。
每个元素都是一个匿名函数(其实四个匿名函数并不完全准确。实际上它们是四个匿名函数的计算值,因为I的后续循环不仅循环了四次,
同时也提供了I的变量引用。四个周期后,I指向值i=3。这时匿名函数开始引用i=3并计算结果。所以会有[6,6,6,6],
因为匿名函数中的I在下面的循环中并不会立即引用I的值,而是只有在嵌套函数运行时才会找到I的值,这个特性就是延迟绑定)
#为了便于理解,你可以把乘法器的内部想象成这样(这个是伪代码,不准确):
定义乘数():
return[x : 3 * x,x : 3 * x,x : 3 * x,x : 3 * x]
因为Python解释器,在遇到lambda(类似于def)时,只是定义一个匿名的函数对象,保存在内存中。只有当这个匿名函数被调用时,
将运行内部表达式,而对于范围(4)中的I是另一个表达式。在开始运行lambda函数之前,必须等到这个表达式结束。此时,I指向3,X指向2。
改进
定义乘数():
#添加了默认参数i=i。
return [lambda x,i=i: i*x for i in range(4)]
print([m(2)for m in multipliers()])
[0, 2, 4, 6]
相当于:
定义乘数():
funcs=[]
对于范围(4):中的I
def bar(x,i=i):
返回x * i
函数追加(条形)
返回函数
print([m(2)for m in multipliers()])
[0, 2, 4, 6]
添加一个i=i后,匿名函数会添加一个默认参数,python函数中的默认参数,
当python解释器遇到def(i=i)或lambda关键字时,必须初始化默认参数。
此时,对于range(4)中的I,匿名函数的默认参数I,每次循环都需要找到对I的引用。
当i=0时,第一个匿名函数的默认参数值为0;当i=1时,第二个匿名函数的默认参数值为1,依此类推。
#为了便于理解,你可以把乘法器的内部想象成这样(这个是伪代码只是为了理解):
定义乘数():
返回[lambda x,i=0: i*x,lambda x,i=1: i*x,lambda x,i=2: i*x,lambda x,i=3:i*x i=3]
# x的引用是2,所以输出的结果是:[0,2,4,6]
当然你的i=i也可以改成A=I。
定义乘数():
#添加了默认参数A=I。
return [lambda x,a=i: x*a for i in range(4)]
print([m(2)for m in multipliers()])
[0, 2, 4, 6]
Python的延迟绑定实际上只在嵌套函数运行时引用外部变量I。不运行时,不寻找I的值,这就是第一个函数输出结果为[6,6,6,6]的原因。
关于Python函数中闭包和延迟绑定的细节,本文到此结束。有关Python延迟绑定的更多信息,请搜索流行的IT软件开发工作室以前的文章,或者继续浏览下面的相关文章。希望大家以后多多支持盛行的IT软件开发工作室!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。