查看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_ *方法仅在拆分时调用,否则在行的其余部分未解析.这提供了消息附带的所有信息,但它并非始终是数据的最佳格式.例如,JOIN消息包括包含主机掩码的用户名,但主机掩码通常是无关紧要的,只需要昵称即可.因此,JOIN执行了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)
您可以看到这里还有一个条件,有时它称为join而不是userJoined.这是从低级数据到应为应用程序开发人员使用的更加方便的转换的另一个示例.
此分层应该可以帮助您确定在处理事件时要覆盖的方法.如果*别的回调(例如userJoined,join或privmsg)足以满足您的要求,则应使用这些回调,因为它们会使您的工作最容易.另一方面,如果它们以不方便的格式显示数据或不方便以其他方式使用,则可以降低到irc_ *级别.您的方法将被调用,而不是在IRCClient上定义的方法,因此您可以使用较低级别的格式处理数据,甚至不会调用较高级别的回调(除非您在覆盖该方法时也调用了基本实现) .
您还会发现有些IRC消息,IRCClient甚至没有为其定义irc_ *方法.如上面在handleCommand方法中所见,所有这些都进入了irc_unknown回调.但是,如果您在IRCClient子类上定义了irc_ *方法,则handleCommand将开始将数据传递给该方法.显然,在这些情况下,您唯一的选择是定义irc_ *方法,因为没有更高级别的回调(如irc_PRIVMSG / privmsg情况下的privmsg).
如果愿意,您可以按照类似于IRCClient的方式来构建irc_ *方法的实现-我通常会发现这样做很有帮助,因为它使单元测试变得更容易,并使协议解析逻辑与应用程序逻辑分离-但这是可行的给你.