gpt4 book ai didi

python - DelegatorBot 在 TelePot 中是如何工作的?

转载 作者:太空狗 更新时间:2023-10-30 01:50:13 25 4
gpt4 key购买 nike

我正在尝试研究 python 库 Telepot通过查看 counter.py此处提供的示例:https://github.com/nickoala/telepot/blob/master/examples/chat/counter.py .
我发现有点难以理解 DelegatorBot类实际上有效。

这是我认为到目前为止我已经理解的内容:

1.

我看到最初正在定义这个类(派生自“ChatHandler”类):

class MessageCounter(telepot.helper.ChatHandler):

def __init__(self, *args, **kwargs):
super(MessageCounter, self).__init__(*args, **kwargs)
self._count = 0

def on_chat_message(self, msg):
self._count += 1
self.sender.sendMessage(self._count)

2.

然后通过实例化类 DelegatorBot 创建一个机器人:
bot = telepot.DelegatorBot(TOKEN, [
pave_event_space()(
per_chat_id(), create_open, MessageCounter, timeout=10
),
])

3.

我知道 DelegatorBot 的新实例创建并放入变量 bot .第一个参数是电报验证此机器人所需的 token ,第二个参数是一个列表,其中包含我不理解的内容。

我的意思是这部分:
pave_event_space()(
per_chat_id(), create_open, MessageCounter, timeout=10
)

然后我的问题是..

pave_event_space()一个被调用的方法返回对另一个方法的引用?然后使用参数 (per_chat_id(), create_open, MessageCounter, timeout=10) 调用返回的方法?

最佳答案

简答

是的,pave_event_space()返回一个函数。让我们称之为 fn . fn然后用 fn(per_chat_id(), create_open, ...) 调用,它返回一个二元组 (seeder function, delegate-producing function) .

如果你想进一步研究代码,这个简短的回答可能不是很有帮助......

更长的答案

了解什么pave_event_space()做了什么以及这一系列的论点意味着什么,我们必须回到基础并理解 DelegatorBot接受作为参数。
DelegatorBot的构造函数是 explained here .简单地说,它接受一个 2 元组列表 (seeder function, delegate-producing function) .为了减少冗长,我将调用第一个元素 播种机和第二个元素 委托(delegate)制作人 .

播种机有此签名 seeder(msg) -> number .对于收到的每条消息,seeder(msg)被调用以生成 number .如果那 number是新的,同伴委托(delegate)生产者(与播种者共享同一元组的那个)将被调用以生成一个线程,该线程用于处理新消息。如果那 number已经被一个正在运行的线程占用了,什么都不做。本质上,播种者对消息进行“分类”。如果它看到一条消息属于一个新的“类别”,它就会产生一个新线程。

委托(delegate)制作人有这个签名 producer(cls, *args, **kwargs) -> Thread .它调用 cls(*args, **kwargs)实例化处理程序对象(在您的情况下为 MessageCounter)并将其包装在线程中,因此处理程序的方法是独立执行的。

(注意:实际上,播种者不一定返回 number 并且委托(delegate)生产者不一定返回 Thread 。为了清楚起见,我在上面进行了简化。See the reference 以获得完整的解释。)

在 Telepot 的早期,一个 DelegatorBot通常是通过透明地提供播种机和委托(delegate)生产者来制作的:

bot = DelegatorBot(TOKEN, [
(per_chat_id(), create_open(MessageCounter, ...))])

后来,我向处理程序(例如 ChatHandler )添加了生成自己的事件(例如超时事件)的功能。每类处理程序都有自己的事件空间,因此不同类的事件不会混合。在每个事件空间中,事件对象本身也有一个源 id 来标识哪个处理程序发出了它。这种架构对播种者和委托(delegate)生产者提出了一些额外的要求。

播种者必须能够“分类”事件(除了外部消息)并返回相同的 number这导致了事件发射器(因为我们不想为这个事件产生一个线程;它应该由事件发射器本身处理)。委托(delegate)生产者还必须将适当的事件空间传递给 Handler 类(因为每个 Handler 类都有一个唯一的事件空间,由外部生成)。

为了让一切正常工作,必须向播种者及其同伴委托(delegate)生产者提供相同的事件空间。和每一双 (seeder, delegate-producer)必须获得全局独一无二的事件空间。 pave_event_space()确保这两个条件,基本上将一些额外的操作和参数修补到 per_chat_id() 上。和 create_open()并确保它们是一致的。

更深的

“修补”究竟是如何完成的?我为什么要你做 pave_event_space()(...)而不是更直接的 pave_event_space(...) ?

首先,回想一下我们的最终目标是拥有一个二元组 (per_chat_id(), create_open(MessageCounter, ...)) . “修补”通常意味着 (1) 将一些额外的操作附加到 per_chat_id() ,以及 (2) 在调用中插入一些额外的参数 create_open(... more arguments here ...) .这意味着我不能让用户拨打 create_open(...)直接因为,一旦被调用,我就不能插入额外的参数。我需要一个更抽象的构造,其中用户指定 create_open但电话 create_open(...)其实是我做的。

想象一个名为 pair 的函数,其签名为 pair(per_chat_id(), create_open, ...) -> (per_chat_id(), create_open(...)) .换句话说,它将第一个参数作为第一个元组元素传递,并通过实际调用 create_open(...) 创建第二个元组元素。与剩余的论点。

现在,它达到了我无法用语言解释源代码的地步(我已经思考了 30 分钟)。 pave_event_space的伪代码看起来像这样:
def pave_event_space(fn=pair):
def p(s, d, *args, **kwargs):
return fn(append_event_space_seeder(s),
d, *args, event_space=event_space, **kwargs)
return p

它需要函数 pair ,并返回 pair -like 函数(签名与 pair 相同),但具有更复杂的播种器和更多参数标记。这就是我所说的“修补”的意思。
pave_event_space是最常见的“修补程序”。其他修补程序包括 include_callback_query_chat_idintercept_callback_query_origin .他们都做基本相同的事情:需要一个 pair -like 函数,返回另一个 pair -like 函数,带有更复杂的播种机和更多参数标记。因为输入和输出是相似的,所以可以将它们链接起来以应用多个补丁。如果您查看 callback examples ,你会看到这样的:
bot = DelegatorBot(TOKEN, [
include_callback_query_chat_id(
pave_event_space())(
per_chat_id(), create_open, Lover, timeout=10),
])

它修补事件空间内容,然后修补回调查询内容,以使播种器( per_chat_id() )和处理程序( Lover )能够协同工作。

这就是我现在能说的。我希望这能对代码有所了解。祝你好运。

关于python - DelegatorBot 在 TelePot 中是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45387797/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com