首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DelegatorBot究竟是如何在TelePot中工作的?

DelegatorBot究竟是如何在TelePot中工作的?
EN

Stack Overflow用户
提问于 2017-07-29 09:45:43
回答 1查看 2.3K关注 0票数 5

我试图通过查看这里可用的Telepot示例来研究python库counter.pyhttps://github.com/nickoala/telepot/blob/master/examples/chat/counter.py

我发现很难理解DelegatorBot类实际上是如何工作的。

这就是我到目前为止所理解的:

1.

首先,我看到这个类(派生自"ChatHandler“类)正在被定义:

代码语言:javascript
复制
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。

代码语言:javascript
复制
bot = telepot.DelegatorBot(TOKEN, [
    pave_event_space()(
        per_chat_id(), create_open, MessageCounter, timeout=10
    ),
])

3.

我了解到创建了一个新的DelegatorBot实例并将其放入变量bot中。第一个参数是电报对这个bot进行身份验证所需的令牌,第二个参数是包含一些我不明白的内容的列表。

我是说这部分:

代码语言:javascript
复制
pave_event_space()(
    per_chat_id(), create_open, MessageCounter, timeout=10
)

然后我的问题是..。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-07-30 07:20:14

简短回答

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

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

较长答案

要理解pave_event_space()做了什么以及这一系列参数意味着什么,我们必须回到基础,并理解DelegatorBot接受什么作为参数。

DelegatorBot的构造函数是在此解释。简单地说,它接受一个由2元组(seeder function, delegate-producing function)组成的列表。

一个播种机有这个签名seeder(msg) -> number。对于收到的每一条消息,seeder(msg)都会被调用以生成一个number。如果该number是新的,则将调用配套的委托生产者(与种子器共享相同元组的代理生产者)来生成一个线程,该线程用于处理新消息。如果该number已被正在运行的线程占用,则不会执行任何操作。在本质上,播种机“分类”的信息。如果它看到一条消息属于一个新的“类别”,就会产生一个新的线程。

委托生产者具有此签名producer(cls, *args, **kwargs) -> Thread。它调用cls(*args, **kwargs)来实例化一个处理程序对象(在您的情况下是MessageCounter),并将它封装在一个线程中,因此处理程序的方法是独立执行的。

(注意:实际上,播种机不一定返回number,委托生产者不一定返回Thread。为了清楚起见,我简化了上面的内容。) 见参考资料的完整解释。)

在电传器的早期,DelegatorBot通常是通过透明地提供播种机和委托生产者来制作的:

代码语言:javascript
复制
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(...)

首先,回顾一下我们的最终目标是拥有一个二元组(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的伪代码如下所示:

代码语言:javascript
复制
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函数,其中有一个更复杂的播种机和更多的参数。因为输入和输出是相同的,所以可以将它们链接起来应用多个补丁程序。如果您查看回调示例,您将看到如下内容:

代码语言:javascript
复制
bot = DelegatorBot(TOKEN, [
    include_callback_query_chat_id(
        pave_event_space())(
            per_chat_id(), create_open, Lover, timeout=10),
])

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

我现在只能说这些。我希望这能让我们对密码有所了解。祝好运。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45387797

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档