我在运行时无法添加命令处理程序,这是一个示例:
from telegram.ext import Updater, CommandHandler
updater = Updater(token)
items = [
('a', 1),
('b', 2),
('c', 3)
]
for i in range(len(items)):
def dummy_func(bot, update):
print(items[i][1])
updater.dispatcher.add_handler(
CommandHandler(items[i][0], dummy_func)
)
updater.start_polling()
例如,我希望/a
在我的控制台中打印1
,但是3
是为a,b或c打印的。我以为函数可能每次都存储在内存中的同一位置,并尝试将回调存储在列表中,但没有帮助。
关于如何执行此操作的任何想法?
答案 0 :(得分:1)
此问题不属于电报漫游器或python-telegram-bot
库。
这只是Python语言的功能。
其背后的原因与著名的lambda functions in list comprehension python行为有些相似。
考虑一下此脚本的简化版本:
items = [
('a', 1),
('b', 2),
('c', 3)
]
handlers = [] # think of dispatcher handlers as a list
for i in range(len(items)):
def dummy_func(): # <--- closure
print(items[i][1])
handlers.append(dummy_func) # somewhat similar to dispatcher.add_handler()
for f in handlers: # let's see the results
f()
它输出的结果与您得到的完全相同:
3
3
3
由于在dummy_func
循环内定义for
并在函子本身内使用items[i][1]
来创建闭包,因此您会得到相同的结果。
问题在于,您可能不希望dummy_func
仅在实际执行特定功能时才引用变量i
。
并且由于它在for
循环完成之后执行,因此i
的值是它在循环中的最后一个值。因此,所有函数都引用相同的i
值,即2
,在这种情况下,items[i][1]
将始终为3
。
Nice article关于Python的作用域和闭包。
有关闭包的GitHub gist。