'METHODNAME'作为客户端方法与irc
查看twisted.words.protocols.irc.IRCClient,在我看来,似乎有一些奇怪的冗余方法。 例如,有一种方法'privmsg',但也有一种方法'irc_PRIVMSG'
作为另一个例子,考虑'join'和'irc_JOIN'
我想知道的是为什么冗余,这些只是许多的两个例子。 两种不同的类型在不同的环境中使用吗? 我们应该使用一种类型而不是另一种?
您正处在正确的轨道上,关于在不同情况下使用的两种不同类型的方法。 通过检查IRCClient
处理接收数据的方式,可以很容易地看到这一点。 首先将它们解析成行,然后将行分割并将其传递给自己的handleCommand
方法:
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()
这是一个模式的例子,在Twisted协议实现中,甚至更一般地,在Python程序中是相当普遍的。 某些输入部分用于动态构建方法名称。 然后getattr
被用来查找该方法。 如果找到了,它被调用。
由于服务器正在发送诸如“PRIVMSG ...”和“JOIN ...”之类的客户端线路,因此IRCClient
查找诸如irc_PRIVMSG
和irc_JOIN
类的方法。
这些irc_*
方法只是用分割来调用,否则就是irc_*
的行的剩余部分。 这提供了与消息一起提供的所有信息,但并不总是数据最好的格式。例如, JOIN
消息包括包含主机掩码的用户名,但通常主机掩码不相关,只需要昵称。 所以JOIN
为irc_*
方法做了一些相当典型的irc_*
:它将粗略的数据变成更愉快的工作,并将结果传递给userJoined
:
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
。 这是将低级数据转换为应用程序开发人员更容易使用的另一个示例。
这种分层可以帮助您决定处理事件时要覆盖哪些方法。 如果最高级别的回调(例如userJoined
, joined
或privmsg
)满足您的要求,那么您应该使用这些回调,因为它们会使您的任务变得最简单。 另一方面,如果他们以不方便的格式显示数据或者以其他方式使用这些数据很尴尬,则可以下降到irc_*
级别。 你的方法将被调用,而不是在IRCClient
定义的IRCClient
,所以你可以用低级格式处理数据,甚至不会调用更高级别的回调(除非你在覆盖方法时也调用基础实现) 。
你还会发现IRCClient
甚至没有定义irc_*
方法。 正如我们在handleCommand
方法中看到的那样,这些都转到了irc_unknown
回调。 但是,如果您在IRCClient
子类上定义了一个irc_*
方法,那么handleCommand
将开始将数据传递给该方法。 显然,在这种情况下,你唯一的选择是定义irc_*
方法,因为没有更高级别的回调(如privmsg
在irc_PRIVMSG
/ privmsg
情况下)。
如果你喜欢,你可以像IRCClient
那样构造你的irc_*
方法的实现 - 我通常觉得这样做很有帮助,因为它使得单元测试更容易,并且使协议解析逻辑与应用逻辑分开 - 但是它已经到了给你。