Python Telegram机器人从列表中添加处理程序

时间:2018-08-25 02:39:20

标签: python telegram telegram-bot

我在运行时无法添加命令处理程序,这是一个示例:

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打印的。我以为函数可能每次都存储在内存中的同一位置,并尝试将回调存储在列表中,但没有帮助。

关于如何执行此操作的任何想法?

1 个答案:

答案 0 :(得分:1)

tldr;

此问题不属于电报漫游器或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