关于python:’METHODNAME’作为客户端方法与irc_’METHODNAME’在twisted中

'METHODNAME' as Client method versus irc_'METHODNAME' in twisted

看看twisted.words.protocols.irc.ircclient,在我看来有一些奇怪的冗余方法。例如,有一个方法"privmsg",但也有一个方法"irc_privmsg"

另一个例子是考虑"join"和"irc_join"

我想知道的是为什么冗余,这只是许多例子中的两个。这两种不同的类型在不同的上下文中使用吗?我们应该使用一种类型而不是另一种类型吗?


对于在不同环境中使用的两种不同类型的方法,您的看法是正确的。通过检查IRCClient处理接收到的数据的方式,可以很容易地看到这一点。首先,它将它们解析成行,然后将这些行拆分,并将片段传递给它自己的handleCommand方法:

1
2
3
4
5
6
7
8
9
10
11
12
def handleCommand(self, command, prefix, params):
   """Determine the function to call for the given command and call
    it with the given arguments.
   """

    method = getattr(self,"irc_%s" % command, None)
    try:
        if method is not None:
            method(prefix, params)
        else:
            self.irc_unknown(prefix, command, params)
    except:
        log.deferr()

这是一个模式的例子,在扭曲的协议实现中非常常见,甚至更普遍地说,在整个Python程序中也是如此。输入的某些部分用于动态构造方法名。然后用getattr查找该方法。如果找到了,就调用它。

由于服务器正在发送"privmsg…"和"join…"等客户机行,这导致IRCClient查找irc_PRIVMSGirc_JOIN等方法。

调用这些irc_*方法时,只需要拆分行的其余部分,否则将无法对其进行分析。这提供了消息附带的所有信息,但对于要使用的数据来说,这并不总是最好的格式。例如,JOIN消息包含包含hostmask的用户名,但hostmask通常不相关,只需要昵称。因此,JOIN做了一些对irc_*方法相当典型的事情:它将粗糙的数据转换成更容易处理的数据,并将结果传递给userJoined

1
2
3
4
5
6
7
8
9
10
def irc_JOIN(self, prefix, params):
   """  
    Called when a user joins a channel.
   """

    nick = string.split(prefix,'!')[0]
    channel = params[-1]
    if nick == self.nickname:
        self.joined(channel)
    else:
        self.userJoined(nick, channel)

你可以看到这里也有一个条件,有时它称为joined,而不是userJoined。这是从低级数据转换为应用程序开发人员更方便使用的数据的另一个示例。

这个层次应该帮助您决定在处理事件时要覆盖哪些方法。如果最高级别的回调,如userJoinedjoinedprivmsg足以满足您的需求,那么您应该使用这些回调,因为它们会使您的任务变得最简单。另一方面,如果它们以不方便的格式显示数据,或者以其他方式使用不方便,则可以将其降到irc_*级别。您的方法将被调用,而不是在IRCClient上定义的方法,因此您可以以较低级别的格式处理数据,甚至不会调用较高级别的回调(除非您在重写该方法时也调用了基实现)。

您还将发现有一些IRC消息,IRCClient甚至没有为其定义irc_*方法。正如我们在上面的handleCommand方法中所看到的,这些都进入irc_unknown回调。但是,如果在IRCClient子类上定义了一个irc_*方法,那么handleCommand将开始向该方法传递数据。显然,在这些情况下,您唯一的选择是定义irc_*方法,因为没有更高级别的回调(如irc_PRIVMSG/privmsg案例中的privmsg)。

如果您愿意的话,您可以按照IRCClient的方式来构造irc_*方法的实现——我通常认为这样做很有帮助,因为它使单元测试更容易,并且使协议解析逻辑与应用程序逻辑分离——但这取决于您自己。