twisted defer的一个bug

3 views
Skip to first unread message

shhgs

unread,
Oct 23, 2010, 10:33:25 PM10/23/10
to pyth...@googlegroups.com

上代码是王道。我们就直接王道吧。

In [1]: from twisted.internet import defer

In [2]: d = defer.Deferred()

In [3]: for i in range(10):
...: d.addCallback(lambda a : a + i)
...:
...:
Out[3]: <Deferred at 0x20fd320>
Out[3]: <Deferred at 0x20fd320>
Out[3]: <Deferred at 0x20fd320>
Out[3]: <Deferred at 0x20fd320>
Out[3]: <Deferred at 0x20fd320>
Out[3]: <Deferred at 0x20fd320>
Out[3]: <Deferred at 0x20fd320>
Out[3]: <Deferred at 0x20fd320>
Out[3]: <Deferred at 0x20fd320>
Out[3]: <Deferred at 0x20fd320>

In [4]: d.callback(0)

In [5]: d
Out[5]: <Deferred at 0x20fd320 current result: 90>

In [6]: d2 = defer.succeed(0)

In [7]: for i in range(10):
...: d2.addCallback(lambda a : a + i)
...:
...:
Out[7]: <Deferred at 0x2100290 current result: 0>
Out[7]: <Deferred at 0x2100290 current result: 1>
Out[7]: <Deferred at 0x2100290 current result: 3>
Out[7]: <Deferred at 0x2100290 current result: 6>
Out[7]: <Deferred at 0x2100290 current result: 10>
Out[7]: <Deferred at 0x2100290 current result: 15>
Out[7]: <Deferred at 0x2100290 current result: 21>
Out[7]: <Deferred at 0x2100290 current result: 28>
Out[7]: <Deferred at 0x2100290 current result: 36>
Out[7]: <Deferred at 0x2100290 current result: 45>

In [8]: d2
Out[8]: <Deferred at 0x2100290 current result: 45>

这个很离谱呀。再接再厉

In [27]: d = defer.Deferred()

In [28]: d.addCallback(lambda a : a + 0)
Out[28]: <Deferred at 0x217ec68>

In [29]: d.addCallback(lambda a : a + 1)
Out[29]: <Deferred at 0x217ec68>

In [30]: d.addCallback(lambda a : a + 2)
Out[30]: <Deferred at 0x217ec68>

In [31]: d.addCallback(lambda a : a + 3)
Out[31]: <Deferred at 0x217ec68>

In [32]: d.callback(0)

In [33]: d
Out[33]: <Deferred at 0x217ec68 current result: 6>

正常。

In [35]: d = defer.Deferred()

In [36]: for i in range(4):
....: d.addCallback(lambda a : a + i)
....:
....:
Out[36]: <Deferred at 0x218e098>
Out[36]: <Deferred at 0x218e098>
Out[36]: <Deferred at 0x218e098>
Out[36]: <Deferred at 0x218e098>

In [38]: d.callback(0)

In [39]: d
Out[39]: <Deferred at 0x218e098 current result: 12>

不正常。


看来
d.addCallback(foo)
d.addCallback(bar)

d.addCallback(foo).addCallback(bar)
之间有微妙的区别。但具体是什么,百思不得其解。望有达人能点点拨一二。


btw: Sorry Leo Jay, 刚才发错邮箱了。


Andelf

unread,
Oct 23, 2010, 10:53:25 PM10/23/10
to pyth...@googlegroups.com


2010/10/24 shhgs <shhgs....@gmail.com>

上代码是王道。我们就直接王道吧。


老问题其实似乎。

Andelf

unread,
Oct 23, 2010, 10:55:02 PM10/23/10
to pyth...@googlegroups.com


2010/10/24 Andelf <and...@gmail.com>



2010/10/24 shhgs <shhgs....@gmail.com>

上代码是王道。我们就直接王道吧。




>>> fs = [(lambda n: i + n) for i in range(10)]
>>> fs[3](4)
13
不觉得该是 3 + 4 = 7 么?
>>> [f(4) for f in fs]
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]
.....撞石头上了... 换 def 看:
>>> fs = []
>>> for i in range(10):
...    def f(n): return i+n
...    fs.append(f)
...
>>> [f(4) for f in fs]
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]
其实这时候已经有点眉目了, 继续看下去:
>>> fs = []
>>> for i in range(10):
...    def f(n, i=i): return i+n
...    fs.append(f)
...
>>> [f(4) for f in fs]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
作者提到 Haskell 是没问题的:
Prelude> let fs = [(\n -> i + n) | i <- [0..9]] 
Prelude> [f(4) | f <- fs]  
[4,5,6,7,8,9,10,11,12,13]


你想明白了么?我觉得是这个原因。
不是 twisted 的关系,
所以 python 不够 functional 其实 

头太晕

unread,
Oct 23, 2010, 11:06:45 PM10/23/10
to pyth...@googlegroups.com
你的问题不在defer,而在lambda

直接上代码了。



>>> for i in range(10):
...     (lambda :i)()
... 
0
1
2
3
4
5
6
7
8
9
>>> funcs = [lambda :i for i in range(10)]
>>> for func in funcs:
...     func()
... 
9
9
9
9
9
9
9
9
9
9
>>> 




2010/10/24 shhgs <shhgs....@gmail.com>


--
来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
发言: pyth...@googlegroups.com
退订: python-cn+...@googlegroups.com (向此发空信即退!)
详情: http://groups-beta.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp

头太晕

unread,
Oct 23, 2010, 11:09:51 PM10/23/10
to pyth...@googlegroups.com


2010/10/24 Andelf <and...@gmail.com>
这个够详细

shhgs

unread,
Oct 23, 2010, 11:25:34 PM10/23/10
to pyth...@googlegroups.com
嗯。看来是跟这个有关。

In [5]: def func(n, l = []):
l.append(n)
print l
...:
...:

In [8]: func(1)
[1]

In [9]: func(2)
[1, 2]

In [10]: func(3)
[1, 2, 3]

这么有个性的东西,已经不能算bug了,得是一个feature吧。

> > 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>(向此发空信即退!)

Shell Xu

unread,
Oct 23, 2010, 11:37:05 PM10/23/10
to pyth...@googlegroups.com
其实这是一个函数和闭包的问题,python的闭包实现是错误的。
首先是大家的问题,一个无聊的语法误解。
>>> fs = []
>>> for i in range(10):
...     def f(n):
...             print locals()
...             return i+n
...     fs.append(f)
...
>>> [f(4) for f in fs]
{'n': 4}
{'n': 4}
{'n': 4}
{'n': 4}
{'n': 4}
{'n': 4}
{'n': 4}
{'n': 4}
{'n': 4}
{'n': 4}
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]

注意locals()的输出,这时候i不在locals中。为了看的更清楚,我们改写代码。

>>> fs = []
>>> for i in range(10):
...     def f(n):
...             print 'i' in globals()
...             return i+n
...     fs.append(f)
...
>>> [f(4) for f in fs]
True
True
True
True
True
True
True
True
True
True
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]

注意到这个错误的原因了吧?我们输出的函数虽然是多个不同的函数对象,但是其对i的引用都是全局的。再执行下面的代码?
>>> i = 100
>>> [f(4) for f in fs]
True
True
True
True
True
True
True
True
True
True
[104, 104, 104, 104, 104, 104, 104, 104, 104, 104]

这根本是个无聊的语法错误。

同样,我们执行下面的程序。

>>> fs = [(lambda n: 'i' in globals()) for i in range(10)]
>>> [f(4) for f in fs]
[True, True, True, True, True, True, True, True, True, True]
>>> fs = [(lambda n: 'i' in globals()) for kkk in range(10)]
>>> kkk

同学们注意了,[for *name* in ...]的机制中,name不是一个被封闭在语法块内部的名称。于是,发生问题的原因也很清楚,我们弄出了一堆引用全局变量的i+n。

下面是闭包的语法。
>>> def a():
...     rslt = []
...     for i in xrange(0, 10):
...             def f(n):
...                     print 'i' in locals(), 'i' in globals()
...                     return i + n
...             rslt.append(f)
...     return rslt
...
>>> fs = a()
>>> [f(4) for f in fs]
True False
True False
True False
True False
True False
True False
True False
True False
True False
True False
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]

咦,出错了,为什么?
正确的闭包实现上,每个函数指针拥有他自己的locals,而且这个结构应当是一个名称栈,顶部的名称定义覆盖底部的。而python的实现中,对一个f的多次定义,虽然生成了多个function object,但是却只使用一个locals与之对应。导致这些locals之间会发生互相干扰。如果i不是一个单纯的变量,而是一个list,还会出现更好玩的现象。是不是有人觉得耳熟?没错,这就是这个定义的问题根源。
def f(a, b, c = []):
--
无能者无所求,饱食而遨游,泛若不系之舟

shhgs

unread,
Oct 24, 2010, 12:22:16 AM10/24/10
to pyth...@googlegroups.com
下面的问题是,这个bug什么时候能修正。

看来很难呀。

> >> 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>(向此发空信即退!)


> >> 详情: http://groups-beta.google.com/group/python-cn
> >> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> >>
> >
> > --
> > 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
> > 发言: pyth...@googlegroups.com

> > 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>(向此发空信即退!)


> > 详情: http://groups-beta.google.com/group/python-cn
> > 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> >
>
>
>
> --
> 无能者无所求,饱食而遨游,泛若不系之舟
>

victor lee

unread,
Oct 24, 2010, 1:30:38 AM10/24/10
to pyth...@googlegroups.com
当年我搞多线程时传lambda也悲剧了。

2010/10/24 shhgs <shhgs....@gmail.com>

lee Alexander

unread,
Oct 24, 2010, 2:09:22 AM10/24/10
to pyth...@googlegroups.com
换个写法不就搞定了,非要蛋痛这个问题呢,龟叔不打算修复就不活拉?
Alexander.Li
+86 15308006505
mail: superp...@gmail.com/superp...@hotmail.com
site:http://alexander-lee.cnblogs.com

Qing Chiang

unread,
Oct 24, 2010, 2:11:08 AM10/24/10
to pyth...@googlegroups.com
不大赞同你的观点呢。我刚刚试了一下,得到了下面的结果:

In [38]: ls = []
In [39]: for i in range(3):
....: def f(k = i):
....: print locals()
....: ls.append(f)
....:
....:

In [40]: ls[0]()
{'k': 0}

In [41]: ls[1]()
{'k': 1}

In [42]: ls[2]()
{'k': 2}

这似乎表明,每一个已定义的 f ,都有自己独立的作用域。
而这段代码:

>>> fs = []
>>> for i in range(10):
... def f(n):
... print locals()
... return i+n
... fs.append(f)

之所以会有问题,在于,代码并没有在 f 的作用域中添加 i 这个变量,
导致每次对 i 的调用,取的都是全局的 i 值。

Shell Xu

unread,
Oct 24, 2010, 8:49:19 AM10/24/10
to pyth...@googlegroups.com
在 2010年10月24日 下午2:11,Qing Chiang <chiang.gm@gmail.com>写道:
不大赞同你的观点呢。我刚刚试了一下,得到了下面的结果:

In [38]: ls  = []
In [39]: for i in range(3):
  ....:     def f(k = i):
  ....:         print locals()
  ....:     ls.append(f)
  ....:
  ....:

In [40]: ls[0]()
{'k': 0}

In [41]: ls[1]()
{'k': 1}

In [42]: ls[2]()
{'k': 2}

这似乎表明,每一个已定义的 f ,都有自己独立的作用域。
而这段代码:

>>> fs = []
>>> for i in range(10):
...     def f(n):
...             print locals()
...             return i+n
...     fs.append(f)

没看明白么?我上来就说了,这是个低级的语法问题,i引用的是全局变量。 



--
无能者无所求,饱食而遨游,泛若不系之舟

Qing Chiang

unread,
Oct 24, 2010, 10:58:49 AM10/24/10
to pyth...@googlegroups.com
事实上,我不大赞同的是这一句:

"而python的实现中,对一个f的多次定义,虽然生成了多个function object,但是却只使用一个locals与之对应。"

按照我的实验结果,每一次重复定义,都会产生一个新的 locals 与这个 func 对应。

值得注意的是,每次调用 locals() 函数的时候,它都会对当前函数的作用域进行一次全面检查(包括 return 语句中
出现的变量名,如果 return 语句中出现了未在当前域定义的变量时,它会对上级域进行递归搜索,一旦搜索到了,
即将该变量名添加到它所返回的 dict 中。而该变量的值,应该总是通过一个指针指向的。这应该才是造成你所得到
的结果的原因。)

呵呵,熄灯了,睡觉~~

在 2010年10月24日 下午8:49,Shell Xu <shell...@gmail.com> 写道:

shhgs

unread,
Oct 24, 2010, 11:31:39 AM10/24/10
to pyth...@googlegroups.com
这个问题很严重的。

> >> <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>


> >> >(向此发空信即退!)
> >> > >> 详情: http://groups-beta.google.com/group/python-cn
> >> > >> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> >> > >>
> >> > >
> >> > > --
> >> > > 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
> >> > > 发言: pyth...@googlegroups.com
> >> > > 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>

> >> <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>


> >> >(向此发空信即退!)
> >> > > 详情: http://groups-beta.google.com/group/python-cn
> >> > > 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> >> > >
> >> >
> >> >
> >> >
> >> > --
> >> > 无能者无所求,饱食而遨游,泛若不系之舟
> >> >
> >> > --
> >> > 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
> >> > 发言: pyth...@googlegroups.com
> >> > 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>(向此发空信即退!)
> >> > 详情: http://groups-beta.google.com/group/python-cn
> >> > 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> >>
> >> --
> >> 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
> >> 发言: pyth...@googlegroups.com
> >> 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>(向此发空信即退!)
> >> 详情: http://groups-beta.google.com/group/python-cn
> >> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> >>
> >
> > --

> > 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
> > 发言: pyth...@googlegroups.com
> > 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>(向此发空信即退!)
> > 详情: http://groups-beta.google.com/group/python-cn
> > 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> >
>
>
>
> --

Shell Xu

unread,
Oct 24, 2010, 11:32:38 AM10/24/10
to pyth...@googlegroups.com
你搞错了。
>>> def a():
...     for i in xrange(0, 10):
...             def f(n):
...                     return i+n
...             fs.append(f)
... 
>>> fs = []
>>> a()
>>> fs
[<function f at 0xb73d8a74>, <function f at 0xb73d8df4>, <function f at 0xb73d8dbc>, <function f at 0xb73dc56c>, <function f at 0xb73dc1b4>, <function f at 0xb73dc17c>, <function f at 0xb73e08b4>, <function f at 0xb73e08ec>, <function f at 0xb73e0924>, <function f at 0xb73e095c>]
>>> fs[0].func_closure == fs[9].func_closure
True

机制上说,def f(k=i)的方法生成的函数,closure中没有k=i的定义。而是default parameters中的。default parameter每个函数一个,因此没有这个问题。

>>> fs = []
>>> def a():
...     for i in xrange(0, 10):
...             def f(n, i=i): return i+n
...             fs.append(f)
>>> fs[0].func_closure
>>> fs[0].func_defaults
(0,)
>>> fs[1].func_defaults
(1,)

下面这个例子说明了default parameter确实是每个函数一个。以及即使如此,为什么还是不能用def f(a=[])的语法。
>>> def a():
...     for i in xrange(0, 10):
...             def f(n, k=[]): k.append(n); print k
...             fs.append(f)
... 
>>> fs = []
>>> a()
>>> fs[0].func_closure
>>> fs[0].func_defaults
([],)
>>> fs[0](10)
[10]
>>> fs[0](10)
[10, 10]
>>> fs[0](10)
[10, 10, 10]
>>> fs[0].func_defaults
([10, 10, 10],)
>>> fs[1](10)
[10]

Shell Xu

unread,
Oct 24, 2010, 11:35:51 AM10/24/10
to pyth...@googlegroups.com
我的建议是将python作为oop语言来使用,不要过度使用函数编程特性。python的很多特性都是模拟出来的,而且模拟的并不正确。如果想用fp,考虑使用lisp,一步到位。
--
无能者无所求,饱食而遨游,泛若不系之舟

shhgs

unread,
Oct 24, 2010, 12:12:39 PM10/24/10
to pyth...@googlegroups.com

这位老兄的看法,我是比较赞同的。那么再回到我们defer的例子里

[10]: def func(incr):
....: print "func locals", locals()
....: def wrapped(base):
....: print "wrapped locals", locals()
....: return base + incr
....: return wrapped

In [16]: for i in range(10):
....: d.addCallback(func(i))
....:
....:
func locals {'incr': 0}
Out[16]: <Deferred at 0x27c7638>
func locals {'incr': 1}
Out[16]: <Deferred at 0x27c7638>
func locals {'incr': 2}
Out[16]: <Deferred at 0x27c7638>
func locals {'incr': 3}
Out[16]: <Deferred at 0x27c7638>
func locals {'incr': 4}
Out[16]: <Deferred at 0x27c7638>
func locals {'incr': 5}
Out[16]: <Deferred at 0x27c7638>
func locals {'incr': 6}
Out[16]: <Deferred at 0x27c7638>
func locals {'incr': 7}
Out[16]: <Deferred at 0x27c7638>
func locals {'incr': 8}
Out[16]: <Deferred at 0x27c7638>
func locals {'incr': 9}
Out[16]: <Deferred at 0x27c7638>

In [17]: d.callback(0)
wrapped locals {'incr': 0, 'base': 0}
wrapped locals {'incr': 1, 'base': 0}
wrapped locals {'incr': 2, 'base': 1}
wrapped locals {'incr': 3, 'base': 3}
wrapped locals {'incr': 4, 'base': 6}
wrapped locals {'incr': 5, 'base': 10}
wrapped locals {'incr': 6, 'base': 15}
wrapped locals {'incr': 7, 'base': 21}
wrapped locals {'incr': 8, 'base': 28}
wrapped locals {'incr': 9, 'base': 36}

In [18]: d
Out[18]: <Deferred at 0x27c7638 current result: 45>

这个函数跟 lambda _ : _ +i 应该是等效的。但是却没有lambda的问题。 如此看来,看来这是一个lambda的问题。


#!/usr/bin/python

from twisted.internet import defer
import pdb

d = defer.Deferred()

for i in range(3):
d.addCallback(lambda _ : _ + i)

pdb.set_trace()

--Return--
\> /dev/shm/tb(11)<module>()->None
-> pdb.set_trace()
(Pdb) pp d
<Deferred at 0x7fcd682b7950>
(Pdb) pp d.callbacks
[((<function <lambda> at 0x7fcd682e55f0>, (), {}),
(<function passthru at 0x14702a8>, None, None)),
((<function <lambda> at 0x1480aa0>, (), {}),
(<function passthru at 0x14702a8>, None, None)),
((<function <lambda> at 0x1480578>, (), {}),
(<function passthru at 0x14702a8>, None, None))]
(Pdb)
[((<function <lambda> at 0x7fcd682e55f0>, (), {}),
(<function passthru at 0x14702a8>, None, None)),
((<function <lambda> at 0x1480aa0>, (), {}),
(<function passthru at 0x14702a8>, None, None)),
((<function <lambda> at 0x1480578>, (), {}),
(<function passthru at 0x14702a8>, None, None))]
(Pdb) f1 = d.callbacks[0][0][0]
(Pdb) f2 = d.callbacks[1][0][0]
(Pdb) f3 = d.callbacks[2][0][0]
(Pdb) f1.func_globals
{'defer': <module 'twisted.internet.defer' from '/usr/lib/python2.6/dist-packages/twisted/internet/defer.pyc'>, 'f2': <function <lambda> at 0x1480aa0>, 'f3': <function <lambda> at 0x1480578>, 'd': <Deferred at 0x7fcd682b7950>, 'f1': <function <lambda> at 0x7fcd682e55f0>, '__builtins__': <module '__builtin__' (built-in)>, '__file__': './tb', '__package__': None, 'i': 2, 'pdb': <module 'pdb' from '/usr/lib/python2.6/pdb.pyc'>, '__return__': None, '__name__': '__main__', '__doc__': None}
(Pdb) f2.func_globals[i]
*** KeyError: 2
(Pdb) f2.func_globals['i']
2
(Pdb) f3.func_globals['i']
2
(Pdb) f1.func_globals['d']
<Deferred at 0x7fcd682b7950>
(Pdb) f2.func_globals['d']
<Deferred at 0x7fcd682b7950>
(Pdb) f3.func_globals['d']
<Deferred at 0x7fcd682b7950>
(Pdb)

lambda 的调试不比function,只能做到这一步了。看来是globals里面的d的引用也有问题。

shhgs

unread,
Oct 24, 2010, 12:15:45 PM10/24/10
to pyth...@googlegroups.com
twisted框架本身就有很浓的functional programming的风格。这个问题是必须正面解决的。

此外,如果你写过parser就知道了,那可是函数到处飞的实现呀。

> > > >> <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>
> > <python-cn%252Buns...@googlegroups.com<python-cn%25252Bun...@googlegroups.com>


> > >
> > > >> >(向此发空信即退!)
> > > >> > >> 详情: http://groups-beta.google.com/group/python-cn
> > > >> > >> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> > > >> > >>
> > > >> > >
> > > >> > > --
> > > >> > > 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
> > > >> > > 发言: pyth...@googlegroups.com
> > > >> > > 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>
> > <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>
> > >

> > > >> <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>
> > <python-cn%252Buns...@googlegroups.com<python-cn%25252Bun...@googlegroups.com>


> > >
> > > >> >(向此发空信即退!)
> > > >> > > 详情: http://groups-beta.google.com/group/python-cn
> > > >> > > 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> > > >> > >
> > > >> >
> > > >> >
> > > >> >
> > > >> > --
> > > >> > 无能者无所求,饱食而遨游,泛若不系之舟
> > > >> >
> > > >> > --
> > > >> > 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
> > > >> > 发言: pyth...@googlegroups.com
> > > >> > 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>
> > <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>
> > >(向此发空信即退!)
> > > >> > 详情: http://groups-beta.google.com/group/python-cn
> > > >> > 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> > > >>
> > > >> --
> > > >> 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
> > > >> 发言: pyth...@googlegroups.com
> > > >> 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>
> > <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>
> > >(向此发空信即退!)
> > > >> 详情: http://groups-beta.google.com/group/python-cn
> > > >> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> > > >>
> > > >
> > > > --

> > > > 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
> > > > 发言: pyth...@googlegroups.com
> > > > 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>
> > <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>
> > >(向此发空信即退!)
> > > > 详情: http://groups-beta.google.com/group/python-cn
> > > > 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> > > >
> > >
> > >
> > >
> > > --

> > > Alexander.Li
> > > +86 15308006505
> > > mail: superp...@gmail.com/superp...@hotmail.com
> > > site:http://alexander-lee.cnblogs.com
> > >
> > > --
> > > 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
> > > 发言: pyth...@googlegroups.com

> > > 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>(向此发空信即退!)
> > > 详情: http://groups-beta.google.com/group/python-cn
> > > 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> >
> > --
> > 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
> > 发言: pyth...@googlegroups.com
> > 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>(向此发空信即退!)
> > 详情: http://groups-beta.google.com/group/python-cn
> > 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> >
>
>
>
> --
> 无能者无所求,饱食而遨游,泛若不系之舟
>
> --
> 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
> 发言: pyth...@googlegroups.com

> 退订: python-cn+...@googlegroups.com (向此发空信即退!)

Menghan Zheng

unread,
Oct 24, 2010, 10:17:21 PM10/24/10
to pyth...@googlegroups.com
"Learning Python"里对这个问题的解释是
"the enclosing scope variable is looked up when the nested functions are later called"
翻译过来就是,enclosing作用域中的变量是在函数执行的时候被查找的。

2010/10/25 shhgs <shhgs....@gmail.com>

双木成林

unread,
Oct 24, 2010, 11:31:00 PM10/24/10
to pyth...@googlegroups.com
其实从虚拟机汇编角度去看一下就比较清楚了

5 0 LOAD_GLOBAL 0 (i)
3 LOAD_FAST 0 (n)
6 BINARY_ADD
7 RETURN_VALUE

上面是foo这个函数的编译后的代码。
他i全都是调用的全局作用域中的i。
还是闭包问题啊。
下面是源代码。
import dis
funcs = []
for i in range(10):
def foo(n):
return i + n
print (dis.dis(foo))
funcs.append(foo)

print (funcs[3](5))

>>>>>>> <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>
>> <python-cn%252Buns...@googlegroups.com<python-cn%25252Bun...@googlegroups.com>
>>>
>>>> <python-cn%252Buns...@googlegroups.com<python-cn%25252Bun...@googlegroups.com>
>> <python-cn%25252Bun...@googlegroups.com<python-cn%2525252Bu...@googlegroups.com>


>>>
>>>>>
>>>>>>>> (向此发空信即退!)
>>>>>>>>>> 详情: http://groups-beta.google.com/group/python-cn
>>>>>>>>>> 严正: 理解列表! 智慧提问!
>> http://wiki.woodpecker.org.cn/moin/AskForHelp
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
>>>>>>>>> 发言: pyth...@googlegroups.com
>>>>>>>>> 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>
>> <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>
>>>
>>>> <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>
>> <python-cn%252Buns...@googlegroups.com<python-cn%25252Bun...@googlegroups.com>
>>>
>>>>>

>>>>>>> <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>
>> <python-cn%252Buns...@googlegroups.com<python-cn%25252Bun...@googlegroups.com>
>>>
>>>> <python-cn%252Buns...@googlegroups.com<python-cn%25252Bun...@googlegroups.com>
>> <python-cn%25252Bun...@googlegroups.com<python-cn%2525252Bu...@googlegroups.com>

>>>>> Alexander.Li
>>>>> +86 15308006505
>>>>> mail: superp...@gmail.com/superp...@hotmail.com
>>>>> site:http://alexander-lee.cnblogs.com
>>>>>
>>>>> --
>>>>> 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
>>>>> 发言: pyth...@googlegroups.com
>>>>> 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>

>> <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>
>>> (向此发空信即退!)
>>>>> 详情: http://groups-beta.google.com/group/python-cn
>>>>> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
>>>>
>>>> --
>>>> 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
>>>> 发言: pyth...@googlegroups.com
>>>> 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>
>> <python-cn%2Bunsu...@googlegroups.com<python-cn%252Buns...@googlegroups.com>
>>> (向此发空信即退!)
>>>> 详情: http://groups-beta.google.com/group/python-cn
>>>> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
>>>>
>>>
>>>
>>>
>>> --
>>> 无能者无所求,饱食而遨游,泛若不系之舟
>>>
>>> --
>>> 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
>>> 发言: pyth...@googlegroups.com

>>> 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>(向此发空信即退!)
>>> 详情: http://groups-beta.google.com/group/python-cn
>>> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
>>
>> --
>> 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
>> 发言: pyth...@googlegroups.com
>> 退订: python-cn+...@googlegroups.com<python-cn%2Bunsu...@googlegroups.com>(向此发空信即退!)
>> 详情: http://groups-beta.google.com/group/python-cn
>> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
>>
>
> --

> 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表)
> 发言: pyth...@googlegroups.com
> 退订: python-cn+...@googlegroups.com (向此发空信即退!)
> 详情: http://groups-beta.google.com/group/python-cn
> 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp

-----------------------------------
Where Python Happens!

mail: linlu...@gmail.com
twitter: @linluxiang

Reply all
Reply to author
Forward
0 new messages