关于封闭的误解 [英] Misunderstanding about closures

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

问题描述

当我在循环体中定义一个函数时,为什么函数不是

" close"在循环可怜?见下面的例子。


谢谢,

Alex


C:\ Documents and Settings\Alexander May> ; python

Python 2.3.3(#51,2003年12月18日,20:22:39)[MSC v.1200 32 bit(Intel)] on

win32

输入help,copyright,credit等等。或许可证或更多信息。

When I define a function in the body of a loop, why doesn''t the function
"close" on the loop vairable? See example below.

Thanks,
Alex

C:\Documents and Settings\Alexander May>python
Python 2.3.3 (#51, Dec 18 2003, 20:22:39) [MSC v.1200 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.

l = []
x in xrange(10):
.. .. def f():

....返回x

.... l.append(f)

... .l
[<函数f在0x008E66F0>,<函数f在0x008E6AB0>,<函数f在

0x008EC130>,<函数f在0x008EC170>,< functi

,f为0x008EC1B0>,<函数f为0x008EC1F0>,<函数f为0x008EC230>,

<函数f为0x008EC270>,< function f在

0x008EC2B0>,<函数f在0x008EC2F0>]对于f in l:
.... f()

....

9

9

9

9

9

9

9

9

9

9


另一方面,以下工作正如我所料。

l = []
def makef(x):
.... def f():

....返回x

....返回f

.... for x in xrange(10):
.... l.append(makef(x))

.... l
[<函数f在0x008E6AB0>,<函数f在0x008EC330>,<函数f在

0x008EC1F0>,<函数f在0x008EC230>,< functi

,f为0x008EC270>,<函数f为0x008EC2B0>,<函数f为0x008EC0F0>,

<函数f为0x008EC370>,< function f at

0x008EC3B0>,<函数f在0x008EC3F0>]对于f in l:
.... f()

....

0

1

2

3

4

5

6

7

8

9
l=[]
for x in xrange(10): .... def f():
.... return x
.... l.append(f)
.... l [<function f at 0x008E66F0>, <function f at 0x008E6AB0>, <function f at
0x008EC130>, <function f at 0x008EC170>, <functi
on f at 0x008EC1B0>, <function f at 0x008EC1F0>, <function f at 0x008EC230>,
<function f at 0x008EC270>, <function f at
0x008EC2B0>, <function f at 0x008EC2F0>] for f in l: .... f()
....
9
9
9
9
9
9
9
9
9
9

On the other hand, the following works as I expected.
l=[]
def makef(x): .... def f():
.... return x
.... return f
.... for x in xrange(10): .... l.append(makef(x))
.... l [<function f at 0x008E6AB0>, <function f at 0x008EC330>, <function f at
0x008EC1F0>, <function f at 0x008EC230>, <functi
on f at 0x008EC270>, <function f at 0x008EC2B0>, <function f at 0x008EC0F0>,
<function f at 0x008EC370>, <function f at
0x008EC3B0>, <function f at 0x008EC3F0>] for f in l: .... f()
....
0
1
2
3
4
5
6
7
8
9


推荐答案

Alexander May写道:
Alexander May wrote:
当我在循环体中定义一个函数时,为什么不是
functionclose在循环可怜?见下面的例子。


亚历克斯,


你的留言标题是正确的:你误解了闭包是如何工作的。

:-)


闭包不会保存绑定到名称的当前值,它会保存名称本身的

引用。如果你稍后将一个不同的值绑定到名称

,那么闭包将看到新的值。


在你的第一个例子中,只有一个本地名称x表示f闭包所引用的每个

的实例,所以它们都看到相同的值。


在第二个例子中,每次调用makef函数,你创建一个属于该实例的makef的新的本地名称x

。因此,当你在makef中创建

时,每个人都会看到自己的价值与其他人无关。


顺便说一下,你会在JavaScript或任何其他语言中看到相同的效果

支持闭包。


-Mike

C:\Documents and Settings\Alexander May> python
Python 2.3.3(#51,2003年12月18日,20:22:39)[MSC v.1200 32 bit(Intel)] on br / > win32
输入help,copyright,credit等等。或许可证或更多信息。
When I define a function in the body of a loop, why doesn''t the
function "close" on the loop vairable? See example below.
Hi Alex,

Your message title is correct: you''re misunderstanding how closures work.
:-)

A closure doesn''t save the current value that''s bound to a name, it saves a
reference to the name itself. If you bind a different value to the name
later, the closure will see that new value.

In your first example, there is a single local name x that each instance of
the f closure refers to, so they all see the same value.

In the second example, each time you call the makef function, you create a
new local name x that belongs to that instance of makef. So when you create
the closures inside makef, each one sees its own value that is unrelated to
the others.

BTW, you''ll see the same effect in JavaScript or any other language that
supports closures.

-Mike
C:\Documents and Settings\Alexander May>python
Python 2.3.3 (#51, Dec 18 2003, 20:22:39) [MSC v.1200 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
l = []
for x in xrange(10):... def f():
..返回x
... l.append(f)
... l [<函数f在0x008E66F0>,<函数f在0x008E6AB0>,<函数f在
0x008EC130>,<函数f在0x008EC170>,< functi
在f上,在0x008EC1B0>,<函数f在0x008EC1F0>,<函数f在
0x008EC230>,<函数f在0x008EC270> ;,<函数f在
0x008EC2B0>,<函数f在0x008EC2F0>]对于f in l:... f()
...
9
9
9
9
9
9
9
9

另一方面,以下按预期工作。
l = []
def makef(x):... def f():
...返回x
。 ..返回f
... for x in xrange(10):... l.append(makef(x))
... l [< function f at 0x008E6AB0>,<函数f在0x008EC330>,<函数f在
0x008EC1F0&g t;,<函数f在0x008EC230>,< functi
在f上,在0x008EC270>,<函数f在0x008EC2B0>,<函数f在
0x008EC0F0>,<函数f在0x008EC370> ;,<函数f在
0x008EC3B0>,<函数f在0x008EC3F0>]对于f in l:... f()
...
0
1
2
3
5
7
8
9
l=[]
for x in xrange(10): ... def f():
... return x
... l.append(f)
... l [<function f at 0x008E66F0>, <function f at 0x008E6AB0>, <function f at
0x008EC130>, <function f at 0x008EC170>, <functi
on f at 0x008EC1B0>, <function f at 0x008EC1F0>, <function f at 0x008EC230>, <function f at 0x008EC270>, <function f at
0x008EC2B0>, <function f at 0x008EC2F0>] for f in l: ... f()
...
9
9
9
9
9
9
9
9
9
9

On the other hand, the following works as I expected.
l=[]
def makef(x): ... def f():
... return x
... return f
... for x in xrange(10): ... l.append(makef(x))
... l [<function f at 0x008E6AB0>, <function f at 0x008EC330>, <function f at
0x008EC1F0>, <function f at 0x008EC230>, <functi
on f at 0x008EC270>, <function f at 0x008EC2B0>, <function f at 0x008EC0F0>, <function f at 0x008EC370>, <function f at
0x008EC3B0>, <function f at 0x008EC3F0>] for f in l: ... f()
...
0
1
2
3
4
5
6
7
8
9




On Mon,07 Jun 2004 03:27:22 GMT,Alexander May

< al ****************@comcast.net>写道:
On Mon, 07 Jun 2004 03:27:22 GMT, "Alexander May"
<al****************@comcast.net> wrote:
当我在循环体中定义一个函数时,为什么函数不是关闭?在循环可怜?见下面的例子。

嗯,我很难用一种形式来表达这个问题的答案

此外,因为这个功能没有 '关闭''循环变量'


Hrmmm

......

好​​的,这个怎么样


x =''a''

for x in range(10):

foo(x)

bar(x)


你期望'x'在bar(x)中有什么价值?


因为这听起来像是你期待它吧(''a'')而不是

吧(9)。


Hrmm,我记得。那是一件C事,不是吗?循环

变量仅在循环内定义。


上帝让快乐。忘了那样的东西。也许在

再过20年我会忘记我所知道的关于静态类型

语言的所有内容并传入黑客Nirvana。

< {{{*>
When I define a function in the body of a loop, why doesn''t the function
"close" on the loop vairable? See example below.
Hmmm, I''m having a hard time phrasing the answer to this in a form
besides, "Because the function doesn''t ''close'' on a loop variable"

Hrmmm
......
Ok, how about this

x = ''a''
for x in range(10):
foo(x)
bar(x)

What value do you expect ''x'' to be in bar(x)?

Because it sounds like you were expecting it to be bar(''a'') instead of
bar(9).

Hrmm, I just remembered. That''s a C thing, isn''t it? The loop
variable being only defined inside the loop.

God that makes to happy. Forgetting stuff like that. Maybe in
another 20 years I''ll forget everything I ever knew about static typed
languages and pass into hacker Nirvana.
<{{{*>






" Michael Geary" <弥** @ DeleteThis.Geary.com>写道:
"Michael Geary" <Mi**@DeleteThis.Geary.com> writes:
Alexander May写道:
Alexander May wrote:
当我在循环体中定义一个函数时,为什么不起作用? ;靠近"在循环可怜?见下面的例子。
你好Alex,

你的消息标题是正确的:你误解了闭包是如何工作的。
: - )
When I define a function in the body of a loop, why doesn''t the
function "close" on the loop vairable? See example below.
Hi Alex,

Your message title is correct: you''re misunderstanding how closures work.
:-)




不一定。见下文。


[snipped]

顺便说一句,你会在JavaScript或任何支持闭包的语言中看到同样的效果。


不太好。事实上,在或多或少开始这一切的语言中,方案,

标准迭代构造''do'确实在

上引入了* new binding *迭代。

;;注意:这是一个有文化的翻译和*不*惯用的方案 - 没有

;; schemer会这样写它

(定义l''());一个空列表


(do((x 0(+ 1 x)));从0开始x,然后在每一步加1

(( = x 10));当x为10时停止
(设置!l(cons(lambda()x)l)));添加一个关闭x的新函数

; *前面的*


(设置!l(反向l));自从我们添加到前面我们

;必须逆转$

((list-ref l 3));得到列表元素3并执行它3;答案



Common Lisp OTOH不 - 像python:


;;这同样是非惯用的(并且在emacs lisp中不起作用,它没有
;;有词法范围)

(defvar l''( ));一个空列表


(do((x 0(+ 1 x)));从0开始x,然后在每一步加1

(( = x 10));当x为10时返回反转列表

(setf l(cons(lambda()x)l)));添加一个关闭x的新函数

; $ * $

(setq l(反向l))的* front *;自从我们添加到前面我们

;必须逆转
(funcall(nth 3 l));获取列表元素3并执行它10



Not necessarily. See below.

[snipped]
BTW, you''ll see the same effect in JavaScript or any other language that
supports closures.
Not quite. In fact in the language that more or less started it all, scheme,
the standard iteration construct ''do'' does indeed introduce a *new binding* on
each iteration.
;; Note: this is is a literate translation and *not* idiomatic scheme -- no
;; schemer would write it like that
(define l ''()) ; an empty list

(do ((x 0 (+ 1 x))) ; start x with 0, then add 1 at each step
((= x 10)) ; stop when x is 10
(set! l (cons (lambda () x) l))) ; add a new function closing over x to
; the *front* of l

(set! l (reverse l)) ; since we added to the front we
; have to reverse l

((list-ref l 3)) ; get list element 3 and execute it 3 ;ANSWER

Common Lisp OTOH doesn''t -- like python:

;; This is similarly non-idiomatic (and won''t work in emacs lisp, which hasn''t
;; got lexical scope)
(defvar l ''()) ; an empty list

(do ((x 0 (+ 1 x))) ; start x with 0, then add 1 at each step
((= x 10)) ; when x is 10 return the reversed list
(setf l (cons (lambda () x) l))) ; add a new function closing over x to
; the *front* of l

(setq l (reverse l)) ; since we added to the front we
; have to reverse l

(funcall (nth 3 l)) ; get list element 3 and execute it 10








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

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