“学习Python,第4版”提到:
the enclosing scope variable is looked up when the nested functions are later called..
但是,我认为当一个函数退出时,它所有的局部引用都会消失。在
def makeActions():
acts = []
for i in range(5): # Tries to remember each i
acts.append(lambda x: i ** x) # All remember same last i!
return acts
makeActions()[n]
对于每个n
都是相同的,因为变量{
我认为当你把}。在
i
看作一个名称而不是某种值时,会发生什么。你的lambda函数执行类似“取x:查找i的值,计算i**x”。。。所以,当你实际运行这个函数时,它会查找i
,然后,所以i
就是{也可以使用当前编号,但必须使Python将其绑定到另一个名称:
这可能看起来很混乱,因为你经常被教导变量和它的值是一样的——这是真的,但只有在实际使用变量的语言中。Python没有变量,只有名称。在
关于你的评论,实际上我可以更好地说明这一点:
^{pr2}$你说你把i改成了6,实际上并不是这样:
i=6
意思是“我有一个值,6
,我想把它命名为i
”。事实上,您已经使用i
作为名称,这对Python来说无关紧要,它只是重新分配名称,而不是更改它的值(这只适用于变量)。在您可以说在
myList = [i, i, i]
中,i
当前指向的任何值(数字5)都会得到三个新名称:mylist[0], mylist[1], mylist[2]
。这与调用函数时发生的情况相同:参数被赋予新的名称。但这可能违背了任何关于列表的直觉。。。在这可以解释示例中的行为:指定}中的所有条目,因为对于同一个值,只有不同的名称!在
mylist[0]=5
、mylist[1]=5
、mylist[2]=5
-难怪当你重新分配i
时,它们不会改变。如果i
是可静音的,例如一个列表,那么更改i
也会影响到{您可以在
=
的左边使用mylist[0]
这个简单的事实证明它确实是一个名称。我喜欢调用=
assign name操作符:它在左边取一个名称,在右边取一个表达式,然后对表达式求值(调用函数,查找名称后面的值),直到它有一个值,最后将名称赋给该值。它不会改变任何东西。在对于Marks关于编译函数的评论:
好吧,引用(和指针)只有在我们有某种可寻址内存时才有意义。存储在你记忆中的某个地方。使用引用意味着去内存中的那个地方并用它做一些事情。问题是Python没有使用这些概念!在
pythonvm没有内存的概念,值在空间的某处浮动,名称是连接到它们的小标记(通过一个红色的小字符串)。名字和价值存在于不同的世界!在
这在编译函数时会产生很大的不同。如果有引用,则知道所引用对象的内存位置。然后您可以简单地用这个位置替换Then reference。 另一方面,名称没有位置,因此(在运行时)您要做的是跟随红色小字符串并使用另一端的任何内容。这就是Python编译函数的方式:在哪里 只要代码中有一个名字,它就会添加一条指令来找出这个名字代表什么。在
所以基本上Python完全编译函数,但是名称被编译为嵌套名称空间中的查找,而不是作为对内存的某种引用。在
当您使用一个名称时,Python编译器将尝试找出它属于哪个名称空间。这将导致从找到的命名空间加载该名称的指令。在
这又回到了原来的问题:在
lambda x:x**i
中,i
被编译为makeActions
命名空间中的查找(因为i
在那里被使用)。Python不知道,也不关心它背后的值(它甚至不必是一个有效的名称)。运行i
的代码将在其原始名称pa中查找并给出或多或少的期望值。在本地引用之所以持久,是因为它们包含在本地作用域中,而本地作用域是闭包保持引用的地方。在
结束时会发生什么:
for
块。在i
的值就会不断变化–对i
的每个赋值都会更新该帧中i
的绑定。在i
的值不再更新。在i
的任何值。因为在for循环中,创建了闭包,但实际上并不是调用闭包,因此调用时的i
的值将是所有循环完成后它所拥有的最后一个值。在makeActions
的调用将创建不同的帧。在这种情况下,您不会重用for循环的前一帧,也不会更新前一帧的i
值。在简而言之:帧就像其他Python对象一样被垃圾回收,在本例中,一个额外的引用被保留在与
for
块相对应的帧周围,这样当for循环超出范围时,它就不会被破坏。在要获得所需的效果,需要为要捕获的
i
的每个值创建一个新帧,并且每个lambda都需要创建一个对该新帧的引用。您不会从for
块本身获得该值,但可以通过调用helper函数来获得,该函数将建立新的框架。请参阅THC4k的答案,了解沿着这些思路的一个可能的解决方案。在相关问题 更多 >
编程相关推荐