简短的回答
是的,pave_event_space()
返回一个函数。让我们称之为fn
。fn
然后用 调用fn(per_chat_id(), create_open, ...)
,它返回一个 2-tuple (seeder function, delegate-producing function)
。
如果您想进一步研究代码,这个简短的答案可能不是很有帮助......
更长的答案
要了解pave_event_space()
这一系列参数的含义和含义,我们必须回到基础并了解什么DelegatorBot
可以作为参数接受。
DelegatorBot
的构造函数在这里解释。简单地说,它接受一个 2-tuples 列表(seeder function, delegate-producing function)
。为了减少冗长,我将调用第一个元素seeder和第二个元素delegate-producer。
播种机具有此签名seeder(msg) -> number
。对于收到的每条消息,seeder(msg)
都会调用以生成一个number
. 如果这number
是新的,则将调用配套的委托生产者(与播种者共享相同元组的那个)来生成一个线程,该线程用于处理新消息。如果它number
已被正在运行的线程占用,则什么也不做。本质上,播种器对消息进行“分类”。如果它看到一条消息属于一个新的“类别”,它就会产生一个新线程。
委托生产者具有此签名producer(cls, *args, **kwargs) -> Thread
。它调用cls(*args, **kwargs)
实例化处理程序对象(MessageCounter
在您的情况下)并将其包装在线程中,因此处理程序的方法是独立执行的。
(注意:实际上,播种者不一定返回 a number
,委托生产者不一定返回 a Thread
。为清楚起见,我在上面进行了简化。请参阅参考资料以获取完整说明。)
在 Telepot 的早期,aDelegatorBot
通常是通过透明地提供播种机和委托生产者来制作的:
bot = DelegatorBot(TOKEN, [
(per_chat_id(), create_open(MessageCounter, ...))])
后来,我向处理程序(例如)添加ChatHandler
了生成自己的事件(例如,超时事件)的能力。每类处理程序都有自己的事件空间,因此不同类的事件不会混合。在每个事件空间中,事件对象本身也有一个源 id来标识哪个处理程序发出了它。这种架构对播种者和委托生产者提出了一些额外的要求。
播种者必须能够“分类”事件(除了外部消息)并返回number
导致事件发射器的相同事件(因为我们不想为此事件产生线程;它应该由事件处理发射器本身)。委托生产者还必须将适当的事件空间传递给 Handler 类(因为每个 Handler 类都有一个唯一的事件空间,由外部生成)。
为了让一切正常工作,必须向播种机及其同伴委托生产者提供相同的事件空间。并且每一对(seeder, delegate-producer)
都必须获得一个全球唯一的活动空间。pave_event_space()
确保这两个条件,基本上将一些额外的操作和参数修补到per_chat_id()
并create_open()
确保它们是一致的。
更深一点
“修补”究竟是如何完成的?为什么我让你做pave_event_space()(...)
而不是更直接pave_event_space(...)
?
首先,回想一下我们的最终目标是拥有一个 2-tuple (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
它接受 function pair
,并返回一个类似pair
的函数(签名与 相同pair
),但带有更复杂的播种器和更多标记的参数。这就是我所说的“修补”。
pave_event_space
是最常见的“修补程序”。其他修补程序包括include_callback_query_chat_id
和intercept_callback_query_origin
. 它们都做基本相同的事情:接受一个类似pair
函数,返回另一个pair
类似函数,带有更复杂的播种器和更多标记的参数。因为输入和输出是相似的,所以它们可以链接起来应用多个补丁。如果您查看回调示例,您将看到如下内容:
bot = DelegatorBot(TOKEN, [
include_callback_query_chat_id(
pave_event_space())(
per_chat_id(), create_open, Lover, timeout=10),
])
它修补事件空间的东西,然后修补回调查询的东西,以使播种器 ( per_chat_id()
) 和处理程序 ( Lover
) 能够内聚地工作。
这就是我现在能说的。我希望这能对代码有所启发。祝你好运。