lambda闭包问题 [英] lambda closure question

查看:68
本文介绍了lambda闭包问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要做的是通过如下列表迭代

来预加载带参数的函数:

class myclass:
.... passdef func(self,arg):
.... print argmylist = [" my"," sample", 列表]对于mylist中的项目:
.... setattr(myclass,item,lamdba self:func(self,item))


这会将一个函数列表附加到类中,使它们在从类实例调用时绑定

方法。这些函数都是类似的,除了他们通过item参数知道他们的名字。

lambda获取底层函数并用它的名称预加载它,

并且由于lambdas支持闭包,它会记住

用于在实际调用它时创建它的项变量:

obj = myclass()
obj.list()
list


这很棒,因为我可以编写一个只需要的通用函数

知道它的名字稍微修改一下它的行为,然后

多次将它附加到一个不同名字的类上。


不幸的是,它没有不行。似乎闭包跟踪动态输入它的变量

- 如果变量在创建

lambda之后发生变化,则lambda仍然引用_variable_而不是

原始_value_,因此得到新值如下:

obj.sample()
listobj.my()



list


至少,这是我从这种行为中推断出的解释。

假设这就是Guido的意图(就像它可以得到的那样充满活力),我不知道该做什么_I_想要它做什么。事实上,我没有b $ b认为有任何方法可以正确生成lambdas而不用编码

作为文字字符串,因为任何尝试使用变量

引用总是会在循环迭代时被修改。


我错过了什么?帮助。

解决方案

Ted Lilley写道:

我想做的是预加载功能通过如下列表迭代

class myclass:... passdef func(self,arg):...打印argmylist = [" my"," sample"," list"]
for mylist中的项目:... setattr(myclass,item,lamdba self:func(self,item))


[snip]

不幸的是,它不起作用。似乎闭包跟踪动态输入的变量 - 如果变量在
之后发生变化lambda被创建,lambda仍然引用_variable_而不是
原始_value_因此得到像这样的新值:
obj.sample()listobj.my()

list

至少,这是我从这种行为中推断出的解释。




这是正确的解释,首席。


假设这是Guido打算用的方式是(它可以得到它可以得到的
动态),我不知道做什么_I_想要它做什么。事实上,我认为没有任何方法可以正确生成lambdas,而无需在名称中编码
作为文字字符串,因为任何尝试使用变量
参考随着循环的迭代,它将永远被修改。




这是这样的。作为原因的一个例子:考虑一个名为printvars()的嵌套函数

。你可以在一个函数中插入各种

的位置来打印出一些局部变量的值。

如果你这样做了,你就不会想要printvars来打印

的价值时间,你呢?


无论如何,这可以解决,但我想它是'不像你想的那样方便。 (你可以在

循环之外定义结晶,但是我把它放在循环中以使它靠近你需要它的地方。)


.. mylist = [" my"," sample"," list"]

..对于mylist中的项目:

。 .def crystalize(x):

..返回lambda self:func(self,x)

.. setattr(myclass,item,crystalize(item))


如果你只使用lambda,那也可以这样做:


.. setattr(myclass,item,(lambda x) :( lambda self:

func(self,x)))(item))


你可能没有意识到这一点,但你知道的是什么重新尝试做的就叫做

" currying" ;;你可能想在Python食谱中搜索食谱

吧。

-

CARL BANKS


Carl Banks写道:

Ted Lilley写道:

不幸的是,它不起作用。似乎闭包跟踪动态输入的变量 - 如果变量在[...]

之后发生变化
至少,这就是我的解释从这种行为中推断出来。



这是正确的解释,首席。



这是有意的。作为原因的一个例子:考虑一个名为printvars()的嵌套函数。您可以在函数中的各个
位置插入以打印出某些局部变量的值。
如果您这样做,您将不希望printvars打印值
时间它被束缚了,不是吗?




允许我不同意(并开始一个新的与封闭混淆的线程:)


我们知道python没有对变量的引用。对于一些新人而言,这可能看起来很烦人,但最终他们理解了这种方式,而没有他们。但是在闭包的情况下

python支持引用!

嵌套函数,似乎做了两件独立的事情:

1)外部局部scoope的引用变量

2)是动态绑定到常量的函数


这两个是独立的,因为在:

##############

def foo():

def nested():

print x

f =嵌套

x =''sassad''

f()

x =''aafdss''

f()

返回f

##################


一旦foo()返回就没有办法修改''x''!

它变成了一种常量。


所以IMVHO,永远不需要这两个功能。你想要

返回一个绑定到本地值的函数。 * xor *使用本地

函数,可以访问本地,就像它们是全局的一样。


假设默认行为是python做了什么Carl

建议(闭包不要跟踪变量),是否会有优雅的pythonic方式实现嵌套函数
$ b来自外部范围的$ b引用变量? (虽然如果找到

这个有用且非pythonic的话)


就个人而言,我认为这是一个有问题的方式lisp

和其他语言定义术语闭包。但是python是不同的IMO,而且引用变量的能力不是很有用。

欢呼,


jfj

---------------

#the President



jfj写道:

Carl Banks写道:

Ted Lilley写道:

不幸的是,它不起作用。似乎闭包跟踪动态输入的变量
- 如果变量在[...]

之后发生变化
至少,这就是我的解释'从这种行为中推断出来。



这是正确的解释,首席。



它就是这样的。作为原因的一个例子:考虑一个名为printvars()的嵌套函数。你可以插入
函数中的各个地方来打印出一些本地
变量的值。如果你这样做了,你不希望printvars在绑定时打印
的值,是吗?



允许我不同意(并开始一个new" confused with closures"



thread :)
我们知道python没有对变量的引用。对于一些新手而言,这看起来很烦人,但最终他们理解了这种方式,而没有他们。但是在闭包的情况下,
python支持引用!




那是对的。它被称为实用性节拍纯度。


问题是什么'更重要:能够使用嵌套的

函数来引用外部范围,或者能够使用嵌套的

函数作为其定义的函数内的闭包? (两个

方法有效地允许使用嵌套函数作为闭包,如果

它在函数返回后使用。)


众神决定,出于实际原因,前者更重要。

我的经验证实了这一点:我发现我使用的嵌套

函数大约有一半是引用外部范围,一半我作为

关闭返回。只有一两次我尝试使用嵌套函数

定义函数。我猜这或多或少是典型的

如何使用嵌套函数。如果是这样,这是正确的决定。

-

CARL BANKS


What I want to do is pre-load functions with arguments by iterating
through a list like so:

class myclass: .... passdef func(self, arg): .... print argmylist = ["my", "sample", "list"]
for item in mylist: .... setattr(myclass, item, lamdba self: func(self, item))

This attaches a list of functions to the class, making them bound
methods when called from a class instance. The functions are all
similar except that they know their name through the item argument.
The lambda takes the underlying function and preloads it with its name,
and since lambdas support closures, it remembers the item variable that
was used to create it when it is actually called like so:
obj = myclass()
obj.list() list

That''s great, since I can write a generic function that just needs to
know its name to make a slight modification to its behavior, then
attach it a bunch of times to a class under different names.

Unfortunately, it doesn''t work. It seems the closure keeps track of
the variable fed to it dynamically - if the variable changes after the
lambda is created, the lambda still references the _variable_ not the
original _value_ and so gets the new value like so:
obj.sample() listobj.my()


list

At least, that''s the explanation I''m deducing from this behavior.
Assuming that''s the way Guido intended it to be (about as dynamic as it
can get), I''m at a loss to do what _I_ want it to do. In fact, I don''t
think there''s any way to generate the lambdas properly without coding
in the name as a literal string, since any attempt to use a variable
reference will always get modified as the loop iterates.

Am I missing something? Help.

解决方案

Ted Lilley wrote:

What I want to do is pre-load functions with arguments by iterating
through a list like so:

class myclass: ... passdef func(self, arg): ... print argmylist = ["my", "sample", "list"]
for item in mylist: ... setattr(myclass, item, lamdba self: func(self, item))
[snip]
Unfortunately, it doesn''t work. It seems the closure keeps track of
the variable fed to it dynamically - if the variable changes after the lambda is created, the lambda still references the _variable_ not the
original _value_ and so gets the new value like so:
obj.sample() listobj.my()

list

At least, that''s the explanation I''m deducing from this behavior.



And that''s the correct explanation, chief.

Assuming that''s the way Guido intended it to be (about as dynamic as it can get), I''m at a loss to do what _I_ want it to do. In fact, I don''t think there''s any way to generate the lambdas properly without coding
in the name as a literal string, since any attempt to use a variable
reference will always get modified as the loop iterates.



It is intended that way. As an example of why that is: consider a
nested function called "printvars()" that you could insert in various
places within a function to print out the value of some local variable.
If you did that, you wouldn''t want printvars to print the values at
the time it was bound, would you?

Anyways, this can be worked around, but I''d suppose it''s not as
convenient as you''d like. (You could define crystalize outside the
loop, but I have it in the loop to keep it near the place where you
need it.)

.. mylist = ["my","sample","list"]
.. for item in mylist:
.. def crystalize(x):
.. return lambda self: func(self,x)
.. setattr(myclass,item,crystalize(item))

If you''re hellbent on only using lambda, that can be done too:

.. setattr(myclass,item,(lambda x:(lambda self:
func(self,x)))(item))

You may not be aware of it, but what you''re trying to do is called
"currying"; you might want to search the Python Cookbook for recipes on
it.
--
CARL BANKS


Carl Banks wrote:

Ted Lilley wrote:

Unfortunately, it doesn''t work. It seems the closure keeps track of
the variable fed to it dynamically - if the variable changes after [...]


At least, that''s the explanation I''m deducing from this behavior.


And that''s the correct explanation, chief.



It is intended that way. As an example of why that is: consider a
nested function called "printvars()" that you could insert in various
places within a function to print out the value of some local variable.
If you did that, you wouldn''t want printvars to print the values at
the time it was bound, would you?



Allow me to disagree (and start a new "confused with closures" thread:)

We know that python does not have references to variables. To some
newcomers this may seem annoying but eventually they understand the
pythonic way and they do without them. But in the case of closures
python supports references!

Nested functions, seem to do two independent things:
1) reference variables of an outer local scoope
2) are functions bound dynamically to constants

These two are independent because in:
##############
def foo():
def nested():
print x
f = nested
x = ''sassad''
f()
x = ''aafdss''
f()
return f
##################

once foo() returns there is no way to modify ''x''!
It becomes a kind of constant.

So IMVHO, one will never need both features. You either want to
return a function "bound to a local value" *xor* "use a local
function which has access to locals as if they were globals".

Supposing the default behaviour was that python does what Carl
suggests (closures don''t keep track of variables), would there
be an elegant pythonic way to implement "nested functions that
reference variables from their outer scope"? (although if find
this little useful and un-pythonic)

Personally, i think that this is a problem with the way lisp
and other languages define the term "closure". But python is
different IMO, and the ability to reference variables is not
useful.
cheers,

jfj
---------------
# the president



jfj wrote:

Carl Banks wrote:

Ted Lilley wrote:

Unfortunately, it doesn''t work. It seems the closure keeps track ofthe variable fed to it dynamically - if the variable changes after [...]


At least, that''s the explanation I''m deducing from this behavior.


And that''s the correct explanation, chief.



It is intended that way. As an example of why that is: consider a
nested function called "printvars()" that you could insert in various places within a function to print out the value of some local variable. If you did that, you wouldn''t want printvars to print the values at the time it was bound, would you?



Allow me to disagree (and start a new "confused with closures"


thread:)
We know that python does not have references to variables. To some
newcomers this may seem annoying but eventually they understand the
pythonic way and they do without them. But in the case of closures
python supports references!



That''s right. It''s called Practicality beats purity.

The question is what''s more important: to be able to use a nested
function to reference the outer scope, or to be able to use a nested
function as a closure inside the function it was defined in? (Both
approaches effectively allow using a nested function as a closure if
it''s used after the function returns.)

The Gods decided, for practical reasons, the former was more important.
My experience bears this out: I find that about half the nested
functions I use are to reference an outer scope, half I return as a
closure. Only once or twice did I try to use a nested function inside
the defining function. I would guess this is more or less typical of
how nested functions are used. If so, it was the right decision.
--
CARL BANKS


这篇关于lambda闭包问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆