我试图在龙卷风主循环中添加多个回调。但是当我运行这段代码:
def task(num):
print 'task %s' % num
if __name__ == '__main__':
for i in range(1,5):
tornado.ioloop.IOLoop.instance().add_callback(callback=lambda: task(num=i))
tornado.ioloop.IOLoop.instance().start()
我得到5次输出:'task 5',而不是task 1..任务5。当我像这样修改main时:
tornado.ioloop.IOLoop.instance().add_callback(callback=lambda: task(1))
tornado.ioloop.IOLoop.instance().add_callback(callback=lambda: task(2))
tornado.ioloop.IOLoop.instance().add_callback(callback=lambda: task(3))
tornado.ioloop.IOLoop.instance().add_callback(callback=lambda: task(4))
一切正常(我在输出中得到task1-task5)。在第一种情况下我做错了什么?
也许有同样的问题,就像在JS?看看这个答案:JavaScript闭包内循环-简单的实际例子
"问题是变量i,在你的每个匿名函数中,都被绑定到函数外的同一个变量。"
try simple test:
def task(num):
print 'task %s' % num
def create_task(num):
tornado.ioloop.IOLoop.instance().add_callback(callback=lambda: task(num))
if __name__ == '__main__':
for i in range(1,5):
create_task(i)
tornado.ioloop.IOLoop.instance().start()
将lambda封装到functools.partial()函数中以解决"指针问题"
IOLoop.instance().add_callback(callback=functools.partial(task, i*10))
tl;博士;
下面是一个"指针问题"的例子:
def task(num):
print(num)
for i in range(1, 6):
print ("poop {0}".format(i))
IOLoop.instance().add_callback(callback=lambda: task(i))
IOLoop.instance().start()
上面i
代码示例中的将是指向range()
当前迭代的值的内存指针。从1到2,再到3、4、5。
Tornado的add_callback()异步函数立即将控制返回给主程序,使得对task()
函数的所有5个调用几乎同时执行。此时i
已经得到了5
的值。
为了快速解决这个问题,使用funtools.partial
函数代替lambda,并研究两者的区别;)
下面是一个没有bug的例子:
IOLoop.instance().add_callback(callback=functools.partial(task, i*10))