\quad
\quad
闲着无聊,看了道面试题,瞬间涨姿势了!特地做个总结~
题目如下:
lst = [lambda x: x*i for i in range(4)]
res = [m(2) for m in lst]
print(res)
上述式子的输出结果:
[0, 2, 4, 6][6, 6, 6, 6]why?
\quad
首先需要知道匿名函数。匿名函数的关键字为lambda,表现形式为:lambda 参数 : 返回值,lambda后面的参数就是函数的形参,冒号后面的表达式就是返回值。
lambda表达式的意义两点:
其次,也是重点,需要知道闭包。
在Python核心编程里,闭包的定义为:如果在一个内部函数里,对外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认定是闭包。
闭包函数:当前函数引用到上一层函数的局部命名空间的变量时就会触发闭包规则。我们说触发了闭包的函数叫做闭包函数,但是要注意一点:只有当调用闭包函数的时候它才会去引用外层函数的变量,因为在调用闭包函数之前,闭包内部的命名空间还不存在。
\quad
i在外层作用域lambda x: x*i 为内层(嵌)函数,他的命名空间中只有 {'x': 1} 没有i,所以运行时会向外层函数(这里是列表解析式函数[])的命名空间中请求i,而当列表解析式运行时,列表解析式命名空间中的i经过循环依次变化为0-->1-->2-->3最后固定为3,所以当 lambda x: x*i内层函数运行时,去外层函数取i每次都只能取到 3。
\quad
解决办法:变闭包作用域为局部作用域。
给内层函数lambda x: x*i增加参数,命名空间中有了用来存储每次的i ,即改成[lambda x, i=i: x*i for i in range(4)]这样每一次,内部循环生成一个Lambda函数时,
都会把i作为默认参数传入Lambda的命名空间。循环4次实际Lambda表达式为:
lambda x, i=0lambda x, i=1lambda x, i=2lambda x, i=3>>> fun = [lambda x, i=i: x*i for i in range(4)]
>>> for item in fun:
>>> print(item(1))
0
1
2
3
\quad
首先,[lambda x: x * i for i in range(4)]等价于如下函数:
def func():
fun_list = []
for i in range(4):
def foo(x):
return x*i
fun_list.append(foo)
return fun_list
调用函数func(),输出func(),可以看到func()是一个包含四个函数的列表:
>>> func()
[<function __main__.func.<locals>.foo(x)>,
<function __main__.func.<locals>.foo(x)>,
<function __main__.func.<locals>.foo(x)>,
<function __main__.func.<locals>.foo(x)>]
为了论证上面的解释,在函数里打印一些信息,查看该函数命名空间及i值变化:
def func():
fun_list = []
for i in range(4):
def foo(x):
print('foo函数中 i {} 命名空间为:{}:'.format(i, locals()))
return x * i
fun_list.append(foo)
print('外层函数 i 为:{} 命名空间为:{}'.format(i, locals()))
return fun_list
当调用函数时:f = func(),会打印如下信息:
>>> f = func()
外层函数 i 为:0 命名空间为:{'fun_list': [<function func.<locals>.foo at 0x00000194AABA8708>], 'foo': <function func.<locals>.foo at 0x00000194AABA8708>, 'i': 0}
外层函数 i 为:1 命名空间为:{'fun_list': [<function func.<locals>.foo at 0x00000194AABA8708>, <function func.<locals>.foo at 0x00000194AAB750D8>], 'foo': <function func.<locals>.foo at 0x00000194AAB750D8>, 'i': 1}
外层函数 i 为:2 命名空间为:{'fun_list': [<function func.<locals>.foo at 0x00000194AABA8708>, <function func.<locals>.foo at 0x00000194AAB750D8>, <function func.<locals>.foo at 0x00000194AABA8798>], 'foo': <function func.<locals>.foo at 0x00000194AABA8798>, 'i': 2}
外层函数 i 为:3 命名空间为:{'fun_list': [<function func.<locals>.foo at 0x00000194AABA8708>, <function func.<locals>.foo at 0x00000194AAB750D8>, <function func.<locals>.foo at 0x00000194AABA8798>, <function func.<locals>.foo at 0x00000194AABA8828>], 'foo': <function func.<locals>.foo at 0x00000194AABA8828>, 'i': 3}
为了排版美观,将输出的函数地址改名为:函数1、2、3。即得到如下输出:
>>> f = func()
外层函数 i 为:0 命名空间为:{'fun_list': [函数1], 'foo': 函数1, 'i': 0}
外层函数 i 为:1 命名空间为:{'fun_list': [函数1, 函数2], 'foo': 函数2, 'i': 1}
外层函数 i 为:2 命名空间为:{'fun_list': [函数1, 函数2, 函数3], 'foo': 函数3, 'i': 2}
外层函数 i 为:3 命名空间为:{'fun_list': [函数1, 函数2, 函数3, 函数4], 'foo': 函数4, 'i': 3}
同时,对f做切片,调用foo()函数之后,可以得到如下输出:
>>> f[0](0), f[0](1), f[0](2), f[0](3)
foo函数中 i 3 命名空间为:{'x': 0, 'i': 3}:
foo函数中 i 3 命名空间为:{'x': 1, 'i': 3}:
foo函数中 i 3 命名空间为:{'x': 2, 'i': 3}:
foo函数中 i 3 命名空间为:{'x': 3, 'i': 3}:
可以看见:就像上面所说的:四次循环中外层函数命名空间中的i从 0-->1-->2-->3最后固定为3,而在此过程中内嵌函数Lambda函数内因为没有定义i,所以只有Lambda函数动态运行时,在自己命名空间中找不到i才去外层函数复制i = 3过来,结果就是所有Lambda函数的i都为 3,导致得不到预计输出结果:[0, 2, 4, 6]只能得到 [6, 6, 6, 6]。
\quad
上面说到了解决办法就是把变闭包作用域为局部作用域。即当在foo()中添加i=i。给内层函数foo()增加默认参数,命名空间中有了用来存储每次的i,这样每一次内部循环生成一个函数时,都会把i作为默认参数传入foo()的命名空间。
def func():
fun_list = []
for i in range(4):
def foo(x, i=i):
return x * i
fun_list.append(foo)
return fun_list
for m in func():
print(m(2))
这样的话,for循环执行时,就已经把 i(0, 1, 2, 3) 的值传给了foo()函数,此时的i已经是foo()函数的内部变量,运行到foo()函数时,就不会到外部函数寻找变量i,直接运行x * i(0, 1, 2, 3),因此最终结果会是 [0, 2, 4, 6]。
\quad
语言区分作用域,是为了复用变量名。引入作用域,相当于给变量划分了各自的“隔离区”,在不同”隔离区“里,查找变量变得很容易。正是因为有了作用域,我们在函数内才可以随意使用变量名,而不担心其与全局变量、其他函数中的变量冲突。
Python是动态类型语言,变量是在定义的时候赋值的。分以下几个方面来理解:
a = 1 赋值时定义变量;from tools import cubie 导入时定义变量cubie;def fun():pass 定义函数,绑定变量fun;def fun(name=None): pass 定义变量name为函数fun的形式变量(也是局部变量),同时定义函数,绑定变量fun;class Car:pass 定义类,绑定类名Car。变量作用域取决于其定义位置。在Python里,只有函数、类、模块会产生作用域,代码块不会产生作用域。作用域按照变量的定义位置可以划分为4类:
嵌套作用域包含了非局部(non-local)和非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类)A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
作用域的查找遵守LEGB规则。即,Python解释器查找变量时,会按照顺序依次查找
局部作用域-->嵌套作用域-->全局作用域-->内建作用域
在任意一个作用域中找到变量则停止查找,所有作用域查找完成没有找到对应的变量,则抛出NameError: name 'xxxx' is not defined的异常。
为了在局部作用域中修改全局变量和自由变量,可以引入global关键字和nonlocal关键字。
\quad
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候
我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的
本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决
基础版云数据库RDS的产品系列包括基础版、高可用版、集群版、三节点企业版,本文介绍基础版实例的相关信息。RDS基础版实例也称为单机版实例,只有单个数据库节点,计算与存储分离,性价比超高。说明RDS基础版实例只有一个数据库节点,没有备节点作为热备份,因此当该节点意外宕机或者执行重启实例、变更配置、版本升级等任务时,会出现较长时间的不可用。如果业务对数据库的可用性要求较高,不建议使用基础版实例,可选择其他系列(如高可用版),部分基础版实例也支持升级为高可用版。基础版与高可用版的对比拓扑图如下所示。优势 性能由于不提供备节点,主节点不会因为实时的数据库复制而产生额外的性能开销,因此基础版的性能相对于