闭包和动态绑定 [英] closures and dynamic binding

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

问题描述

大家好,


对我来说,这是一种有点不直观的行为。我想讨论一下我不理解的

部分。


>> f = [无] * 10
对于范围内的n(10):



.... f [n] = lambda:n

....


>> f [0]()



9


>> f [1]()



9


我想我到目前为止可以接受这个部分,虽然它花了一点时间

。我正在编写一些代码并找到以下解决方法,

但我不认为它应该给出不同的结果。也许我不是

了解闭包的一些细节。


>> f = [无] * 10
适用于范围内的数字(10):



.... f [n] =(lambda n:(lambda:n))(n)

....


>> f [0]()



0


>> f [1]()



1


这当然是理想的效果。为什么不是第二个

只是在我调用f [0]时查看'n'是什么,然后返回9?

解决方案

2008年9月27日星期六21:43:15 -0700,Aaron \Castironpi \ Brady写道:


对我而言,这是一种有点不直观的行为。我想讨论一下我不理解的

部分。


>> ;> f = [无] * 10
对于范围内的n(10):



... f [n] = lambda:n

...


>>> f [0]()



9


>>> ; f [1]()



9



`n`被查找当``f [0]``被调用。那时它是绑定到9的b $ b。


> ;>> f = [无] * 10
对于范围内的n(10):



... f [n ] =(lambda n:(lambda:n))(n)...


>>> f [ 0]()



0


> ;>> f [1]()



1


这当然是理想的影响。为什么第二个只是

当我调用f [0]并返回9时,查找'n'是什么?



它*在你调用``f [0]``时*会查找`n`但是这次它是

外部``lambda``函数的本地`n`,无论函数被调用,它都绑定到
。当时它被称为

全局`n`被绑定为0.如果你没有命名它可能会更清楚

它是`:


在[167]中:f = [无] * 10


在[168]中:for x in xrange(10) :

.....:f [n] =(lambda x:lambda:x)(n)

.....:


在[169]中:f [0]()

输出[169]:0


Ciao,

Marc''BlackJack''Rintsch


9月28日,1:14 * am,Marc''BlackJack''Rintsch< bj _... @ gmx.netwrote:


2008年9月27日星期六21:43:15 -0700,Aaron \Castironpi \ Brady写道:


对我来说,这是一种有点不直观的行为。 *我想讨论

部分,我不明白。


>> f = [无] * 10
适用于范围内的n(10) :



... * * f [n] = lambda:n

...


>> f [0]()



9


>> f [1]()



9



`n`被抬头看调用时间``f [0]``。 *当时它是

绑定到9.


>> f = [无] * 10
对于范围内的n(10):



... * * f [n] =(lambda n:(lambda:n) )(n)...


>> f [0]()



0


>> f [1]()



1


这当然是预期的效果。 *为什么不是第二个只是

当我调用f [0]并且返回9时,查找'n'是什么?



它*在你调用``f [0]`时查找`n`但是这次它是

外部``lambda``函数的本地`n`,无论函数被调用,它都绑定到
。 *当时它被称为

全局`n`被绑定为0. *如果你没有命名,可能会更清楚

它`n`:


在[167]中:f = [无] * 10


在[168]中:for x in xrange( 10):

* * .....:* * f [n] =(lambda x:lambda:x)(n)

* * ... ..:


在[169]中:f [0]()

输出[169]:0


Ciao,

* * * * Marc''BlackJack''Rintsch



嗨Marc,


我的理解是'n'每次通过

循环获得一个新值。第一遍n = 0,第二遍n = 1,依此类推。 n =

9结尾,这就是为什么`lambda:n`总是返回9.它查询

变量''n'',并查找9.(这很冗长。我开始思考

。)


在您的间接示例版本中,它查询变量''x'' ,

,它在每个f元素的新不同范围内找到。在f [0]中,x =

0.在f [1]中,x = 1.整个有10个不同的''x''变量

的内容F。直接的例子不会分配这个分配给你的b $ b十个不同的''x'。


它有点帮助。我想我觉得以下更像是

我正在寻找:


(非标准)


>> f = [无] * 10
对于范围内的n(10):



.... f [n] = n

....


>> f [0]



9


>> f [1]



9


因为当你访问f [0]时,它会查找变量'' N ''。显然

没有。


(非生产)


>> f = [无] * 10
适用于范围(10)中的n:



.... f [n] =迟到(n)#dear / lazy

....


>> f [0]



9


>> f [1]



9


>> f = [无] * 10
对于范围(10)中的n:



.... f [n ] =早期(n)#early / eager

....


>> f [0]



0


>> f [1]



1


对于函数,我想要一个返回''n的函数'',要么晚了要么

.


(非生产)


>> for n in range(10):



。 ... f [n] = lambda:late(n)


>> f [0]()



9


>> for n in range(10):



.... f [n] = lambda:early(n)


> ;> f [0]()



0


我不喜欢我想你可以把它拉下来。 迟到和早期成功

在n,早期('n'')和晚期('n'')附近引用,直接

作业,但功能并不那么幸运。 ''n''在早期获得任何控制权的时候已经进入了一个更好的世界。


这可能会取得一些成功。


(非生产)


>> ;对于范围(10)中的n:



.... f [n] = late(lambda:n)


>> f [0]()



9


>> ;对于范围(10)中的n:



.... f [n] = early(lambda:n)


>> f [0]()



0


虽然我已经超出了我的预见,但是如果说的那样是否可行,如果

你需要报价,你需要多少内省等等。另外,

''迟'''和''早''是先前接受引用的参数。怎么

他们会看到一个函数?一个简单的装饰师可以提供这个服务吗?


在关于mutable的切线上,不是那个数字,字符串和

元组本身是不可变的,它只是因为它们没有任何改变它们(或可分配的属性)的方法。列表和

词典。这取决于用户是否自定义类。


AaronCastironpi Brady写道:


大家好,


对我而言,这是一种有点不直观的行为。我想讨论一下我不理解的

部分。


>> ;> f = [无] * 10
对于范围内的n(10):



... f [n] = lambda:n



这相当于


范围内的n(10):

def g():返回n

f [n] = g


相当于


def g():返回n

f = [g] * 10

n = 9


>>> f [0]()



9
< blockquote class =post_quotes>


>>> f [1]()



9



这使得这并不像原来的lambda版本那么令人惊讶。

有些人。

我想我到目前为止可以接受这个部分,虽然它花了一点时间来获得

。我正在编写一些代码并找到以下解决方法,

但我不认为它应该给出不同的结果。也许我不是理解关闭的一些细节。


>> > f = [无] * 10
对于范围内的n(10):



... f [n] =( lambda n:(lambda:n))(n)



这相当于


范围内的n(10 ):

def g(n):

def h:

返回n

返回h
f [n] = g(n)


现在,为了避免'n'的不必要的混淆,g相当于


def g(x):

def h:

返回x

返回h

(当然,也可以在lambdas中进行相同的更改)。

以便g(n)()== n,并在每个闭包中存储n。 ..


...


>>> ; f [0]()



0


>>> f [1]()



1



每次调用时都要反刍。


Terry Jan Reedy


Hello all,

To me, this is a somewhat unintuitive behavior. I want to discuss the
parts of it I don''t understand.

>>f= [ None ]* 10
for n in range( 10 ):

.... f[ n ]= lambda: n
....

>>f[0]()

9

>>f[1]()

9

I guess I can accept this part so far, though it took a little getting
used to. I''m writing some code and found the following workaround,
but I don''t think it should give different results. Maybe I''m not
understanding some of the details of closures.

>>f= [ None ]* 10
for n in range( 10 ):

.... f[ n ]= (lambda n: ( lambda: n ) )( n )
....

>>f[0]()

0

>>f[1]()

1

Which is of course the desired effect. Why doesn''t the second one
just look up what ''n'' is when I call f[0], and return 9?

解决方案

On Sat, 27 Sep 2008 21:43:15 -0700, Aaron \"Castironpi\" Brady wrote:

To me, this is a somewhat unintuitive behavior. I want to discuss the
parts of it I don''t understand.

>>>f= [ None ]* 10
for n in range( 10 ):

... f[ n ]= lambda: n
...

>>>f[0]()

9

>>>f[1]()

9

`n` is looked up at the time ``f[0]`` is called. At that time it is
bound to 9.

>>>f= [ None ]* 10
for n in range( 10 ):

... f[ n ]= (lambda n: ( lambda: n ) )( n ) ...

>>>f[0]()

0

>>>f[1]()

1

Which is of course the desired effect. Why doesn''t the second one just
look up what ''n'' is when I call f[0], and return 9?

It *does* look up `n` at the time you call ``f[0]`` but this time it''s
the local `n` of the outer ``lambda`` function and that is bound to
whatever the function was called with. At the time it was called the
global `n` was bound to 0. Maybe it get''s more clear if you don''t name
it `n`:

In [167]: f = [None] * 10

In [168]: for n in xrange(10):
.....: f[n] = (lambda x: lambda: x)(n)
.....:

In [169]: f[0]()
Out[169]: 0

Ciao,
Marc ''BlackJack'' Rintsch


On Sep 28, 1:14*am, Marc ''BlackJack'' Rintsch <bj_...@gmx.netwrote:

On Sat, 27 Sep 2008 21:43:15 -0700, Aaron \"Castironpi\" Brady wrote:

To me, this is a somewhat unintuitive behavior. *I want to discuss the
parts of it I don''t understand.

>>f= [ None ]* 10
for n in range( 10 ):

... * * f[ n ]= lambda: n
...

>>f[0]()

9

>>f[1]()

9


`n` is looked up at the time ``f[0]`` is called. *At that time it is
bound to 9.

>>f= [ None ]* 10
for n in range( 10 ):

... * * f[ n ]= (lambda n: ( lambda: n ) )( n ) ...

>>f[0]()

0

>>f[1]()

1

Which is of course the desired effect. *Why doesn''t the second one just
look up what ''n'' is when I call f[0], and return 9?


It *does* look up `n` at the time you call ``f[0]`` but this time it''s
the local `n` of the outer ``lambda`` function and that is bound to
whatever the function was called with. *At the time it was called the
global `n` was bound to 0. *Maybe it get''s more clear if you don''t name
it `n`:

In [167]: f = [None] * 10

In [168]: for n in xrange(10):
* *.....: * * f[n] = (lambda x: lambda: x)(n)
* *.....:

In [169]: f[0]()
Out[169]: 0

Ciao,
* * * * Marc ''BlackJack'' Rintsch

Hi Marc,

It''s my understanding that ''n'' gets a new value every time through the
loop. n= 0 on the first pass, n= 1 on the second pass, and so on. n=
9 by the end, and that''s why `lambda: n` always returns 9. It queries
the variable ''n'', and finds 9. (This got lengthy. I started thinking
aloud.)

In your version of the indirect example, it queries the variable ''x'',
which it finds in a new distinct scope in each f element. In f[0], x=
0. In f[1], x= 1. There are 10 different ''x'' variables throughout
the contents of f. The direct example does not do this allocation of
ten different ''x''s.

It''s sort of helping. I think I feel like the following is more like
what I''m looking for:

(Non-standard)

>>f= [ None ]* 10
for n in range( 10 ):

.... f[ n ]= n
....

>>f[0]

9

>>f[1]

9

because when you access f[0], it looks up the variable ''n''. Obviously
not.

(Unproduced)

>>f= [ None ]* 10
for n in range( 10 ):

.... f[ n ]= late( n ) #late/lazy
....

>>f[0]

9

>>f[1]

9

>>f= [ None ]* 10
for n in range( 10 ):

.... f[ n ]= early( n ) #early/eager
....

>>f[0]

0

>>f[1]

1

For the functions, I want a function that returns ''n'', either late or
early.

(Unproduced)

>>for n in range( 10 ):

.... f[ n ]= lambda: late( n )

>>f[0]()

9

>>for n in range( 10 ):

.... f[ n ]= lambda: early( n )

>>f[0]()

0

I don''t think you could pull this off. ''late'' and ''early'' succeed
with quotes around n, early(''n'') and late(''n''), in the direct
assignments, but the functions aren''t so lucky. ''n'' has gone on to a
better world by the time ''early'' gets any control.

This might have some success.

(Unproduced)

>>for n in range( 10 ):

.... f[ n ]= late( lambda: n )

>>f[0]()

9

>>for n in range( 10 ):

.... f[ n ]= early( lambda: n )

>>f[0]()

0

Though it''s beyond my foresight to tell if it''s feasible as stated, if
you need quotes, how much introspection you would need, etc. Plus,
''late'' and ''early'' were accepting quoted parameters earlier. How
would they look inside a function? Could a simple decorator provide
the service?

On a tangent about mutables, it''s not that numbers, strings, and
tuples are ''immutable'' per se, it''s just that they don''t have any
methods which mutate them (or assignable properties). Lists and
dictionaries do. It''s up to the user whether a custom class does.


Aaron "Castironpi" Brady wrote:

Hello all,

To me, this is a somewhat unintuitive behavior. I want to discuss the
parts of it I don''t understand.

>>>f= [ None ]* 10
for n in range( 10 ):

... f[ n ]= lambda: n

This is equivalent to

for n in range(10):
def g(): return n
f[n] = g

which is equivalent to

def g(): return n
f = [g]*10
n = 9

>>>f[0]()

9

>>>f[1]()

9

which make this not so surprising as the original lambda version is to
some people.

I guess I can accept this part so far, though it took a little getting
used to. I''m writing some code and found the following workaround,
but I don''t think it should give different results. Maybe I''m not
understanding some of the details of closures.

>>>f= [ None ]* 10
for n in range( 10 ):

... f[ n ]= (lambda n: ( lambda: n ) )( n )

This is equivalent to

for n in range(10):
def g(n):
def h:
return n
return h
f[n] = g(n)

Now, to avoid the needless confusion of ''n''s, g is equivalent to

def g(x):
def h:
return x
return h

(One could do the same change in the lambdas, too, of course).
so that g(n)() == n, with n stored in each closure h...

...

>>>f[0]()

0

>>>f[1]()

1

to be regurgitated when each is called.

Terry Jan Reedy


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

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