Python函数——闭包延迟绑定
前言
请看下面代码
def multipliers():
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],这段代码相当于
def multipliers():
funcs = []
for i in range(4):
def bar(x):
return x*i
funcs.append(bar)
return funcs
print ([m(2) for m in multipliers()] )
"""
[6, 6, 6, 6]
"""
解答
运行代码,解释器碰到了一个列表解析,循环取multipliers()函数中的值,而multipliers()函数返回的是一个列表对象,这个列表中有4个元素,
每个元素都是一个匿名函数(实际上说是4个匿名函数也不完全准确,其实是4个匿名函数计算后的值,因为后面for i 的循环不光循环了4次,
同时提还提供了i的变量引用,等待4次循环结束后,i指向一个值i=3,这个时候,匿名函数才开始引用i=3,计算结果。所以就会出现[6,6,6,6],
因为匿名函数中的i并不是立即引用后面循环中的i值的,而是在运行嵌套函数的时候,才会查找i的值,这个特性也就是延迟绑定)
# 为了便于理解,你可以想象下multipliers内部是这样的(这个是伪代码,并不是准确的): def multipliers():
return [lambda x: 3 * x, lambda x: 3 * x, lambda x: 3 * x, lambda x: 3 * x]
因为Python解释器,遇到lambda(类似于def),只是定义了一个匿名函数对象,并保存在内存中,只有等到调用这个匿名函数的时候,
才会运行内部的表达式,而for i in range(4) 是另外一个表达式,需等待这个表达式运行结束后,才会开始运行lambda 函数,此时的i 指向3,x指向2
改进
def multipliers():
# 添加了一个默认参数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]
"""
相当于
def multipliers():
funcs = []
for i in range(4):
def bar(x, i=i):
return x * i
funcs.append(bar)
return funcs
print ([m(2) for m in multipliers()] )
"""
[0, 2, 4, 6]
"""
解答
添加了一个i=i后,就给匿名函数,添加了一个默认参数,而python函数中的默认参数,
是在python 解释器遇到def(i=i)或lambda 关键字时,就必须初始化默认参数,
此时for i in range(4),每循环一次,匿名函数的默认参数i,就需要找一次i的引用,
i=0时,第一个匿名函数的默认参数值就是0,i=1时,第二个匿名函数的默认参数值就是1,以此类推
# 为了便于理解,你可以想象下multipliers内部是这样的(这个是伪代码只是为了理解): def multipliers():
return [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 所以output的结果就是:[0,2,4,6]
当然你的i=i,也可以改成a=i。
def multipliers():
# 添加了一个默认参数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函数-闭包的概念
一个函数和它的环境变量合在一起,就构成了一个闭包(closure).在Python中,所谓的闭包是一个包含有环境变量取值的函数对象.环境变量取值被保存在函数对象的__closure__属性中.比如下面 ...
- python函数闭包-装饰器-03
可调用对象 callable() # 可调用的(这个东西加括号可以执行特定的功能,类和函数) 可调用对象即 callable(对象) 返回为 True 的对象 x = 1 print(cal ...
- python 函数闭包()
闭包(closure) 当一个函数在内部定义函数,并且内部的函数应用外部函数的参数或者局部变量,当内部函数被当做返回值的时候,相关参数和变量保存在返回函数中,这种结果,叫闭包 example1: de ...
- python 函数 闭包 (节省内存空间 html 获取网页的源码)
#闭包:嵌套函数,内部函数调用外部函数的变量 # def outer(): # a = 1 # def inner(): # print(a) # inner() # outer() def oute ...
- python 函数--闭包函数
一.闭包函数: 在一个外函数中定义一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用. 二.实例: def outer(a): #外函数 b = 10 #临时变量 def i ...
- python闭包和延迟绑定
一.什么是闭包: 1.函数内定义函数. 2.外函数的返回时内函数的引用. 3.内函数使用外函数的局部变量(至少一个). 1 def outfunc(): 2 for num in range(4): ...
- python 延迟绑定
def multipliers(n): funcs = [] for i in range(n): def f(x): return x * i funcs.append(f) return func ...
- Python函数的作用域规则和闭包
作用域规则 命名空间是从名称到对象的映射,Python中主要是通过字典实现的,主要有以下几个命名空间: 内置命名空间,包含一些内置函数和内置异常的名称,在Python解释器启动时创建,一直保存到解释器 ...
- Python函数——命名空间与闭包
前言 执行以下代码 def my_test(): x = 1 y = x+1 print(x) >> Traceback (most recent call last): File &qu ...
随机推荐
- Metasploit用法大全
Metasploit用户接口msfconsoleArmitage: KaliGUI启动:armitage命令启动 Metasploit功能程序msfvenom集成了载荷生成器.载荷编码器.空指令生成 ...
- 863. All Nodes Distance K in Binary Tree 到制定节点距离为k的节点
[抄题]: We are given a binary tree (with root node root), a target node, and an integer value K. Retur ...
- 65. Valid Number 判断字符串是不是数字
[抄题]: Validate if a given string is numeric. Some examples:"0" => true" 0.1 " ...
- 飞鱼星、H3C企业路由器配置
飞鱼星企业路由器配置外网访问IIS 只配置端口映射就行,配置好了,如果不立即重启,需要等几分钟才能生效 H3C路由器配置虚拟服务器即可
- linux下安装python,Django,虚拟环境
linux下python安装步骤: 1.下载python3源码包 wget https://www.python.org/ftp/python/3.6.6/Python-3.6.7.tgz 2.下载p ...
- Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: javax/jms/JMSContext
参考链接 : https://blog.csdn.net/angus_Lucky/article/details/82811946?utm_source=blogxgwz7 org.springfra ...
- eclipse-查看继承层次图/继承实现层次图
阅读代码时,如果想要看某个类继承了哪些类.实现了哪些接口.哪些类继承了这个类,恰巧这个类的继承实现结构又比较复杂,那么如果对开发工具不是很熟练,这个需求是比较难以实现的.eclipse中的type h ...
- MongoDB 官网教程 下载 安装
官网:https://www.mongodb.com/ Doc:https://docs.mongodb.com/ Manual:https://docs.mongodb.com/manual/ 安装 ...
- cpp 区块链模拟示例(三)新基本原形工程的建立
/* 作 者: itdef 欢迎转帖 请保持文本完整并注明出处 技术博客 http://www.cnblogs.com/itdef/ 技术交流群 群号码:432336863欢迎c c++ window ...
- ubuntu中给python3安装opencv
一.安装相关工具包******注意:以下3,4,5,6为可选项,根据需求安装******1.更新库 sudo apt-get update sudo apt-get upgrade 2.安装从源码构建 ...