“方法名称”作为客户端方法与 irc_'METHODNAME'扭曲中
看看twisted.words.protocols.irc.IRCClient,在我看来,有一些奇怪的冗余方法。例如,有一个方法“privmsg”,但也有一个方法“irc_PRIVMSG”
作为另一个例子,考虑“join”和“irc_JOIN”
我想知道为什么会出现冗余,这些只是许多例子中的两个例子。这两种不同的类型是否在不同的上下文中使用?我们应该使用一种类型而不是另一种吗?
Looking at twisted.words.protocols.irc.IRCClient, it seems to me like there are some strangely redundant methods. For instance, there is a method 'privmsg' but also a method 'irc_PRIVMSG'
As another example consider 'join' and 'irc_JOIN'
What I want to know is why the redundancy, those are just two examples of many. Are the two different types used in different contexts? Are we supposed to use one type and not another?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
关于在不同上下文中使用的两种不同类型的方法,您的思路是正确的。实际上,通过检查 IRCClient 处理其接收的数据的方式可以很容易地看出这一点。首先,它将它们解析为行,然后将行拆分并将这些片段传递给自己的
handleCommand
方法:这是 Twisted 协议实现中非常常见的模式示例,更一般地说,在Python程序中作为一个整体。输入的某些部分用于动态构造方法名称。然后使用 getattr 来查找该方法。如果找到,则调用它。
由于服务器正在发送诸如“PRIVMSG ...”和“JOIN ...”之类的客户端行,这会导致
IRCClient
查找诸如irc_PRIVMSG
和之类的方法irc_JOIN
。这些
irc_*
方法只是在拆分行但未解析其余部分的情况下调用。这提供了消息附带的所有信息,但它并不总是数据的最佳格式。例如,JOIN
消息包含包含主机掩码的用户名,但主机掩码通常是无关紧要,只需要昵称。因此,JOIN
做了一些对于irc_*
方法来说相当典型的事情:它将粗略的数据变成更易于使用的数据,并将结果传递给userJoined:
你可以看到这里还有一个条件,有时它会调用
joined
而不是userJoined
。这是从低级数据转换为更方便应用程序开发人员使用的数据的另一个示例。这种分层应该可以帮助您决定在处理事件时要重写哪些方法。如果最高级别的回调(例如
userJoined
、joined
或privmsg
足以满足您的要求,那么您应该使用它们,因为它们会让您的任务变得最简单。另一方面,如果它们以不方便的格式呈现数据或难以以其他方式使用,您可以下降到irc_*
级别。您的方法将被调用,而不是在IRCClient
上定义的方法,因此您可以以较低级别的格式处理数据,并且甚至不会调用较高级别的回调(除非您还调用了基类)当您重写该方法时的实现)。您还会发现有些 IRC 消息
IRCClient
甚至没有为其定义irc_*
方法。正如我们在上面的handleCommand
方法中看到的,这些都进入了irc_unknown
回调。但是,如果您在IRCClient
子类上定义了irc_*
方法,则handleCommand
将开始将数据传递给该方法。显然,在这些情况下,您唯一的选择是定义irc_*
方法,因为没有更高级别的回调(例如irc_PRIVMSG
中的privmsg
>/privmsg
案例)。如果您愿意,您可以像
IRCClient
那样构造您的irc_*
方法的实现 - 我通常发现这样做很有帮助,因为它使单元测试变得更容易并且将协议解析逻辑与应用程序逻辑分开 - 但这取决于您。You're on the right track about the two different types of methods being used in different contexts. This can actually be seen quite easily by examining the way
IRCClient
handles data it receives. First it parses them into lines, then it splits the lines up and passes the pieces to its ownhandleCommand
method:This is an example of a pattern that's quite common in Twisted protocol implementations and, even more generally, in Python programs as a whole. Some piece of the input is used to construct a method name dynamically. Then
getattr
is used to look up that method. If it is found, it is called.Since the server is sending the client lines like "PRIVMSG ..." and "JOIN ...", this results in
IRCClient
looking up methods likeirc_PRIVMSG
andirc_JOIN
.These
irc_*
methods are just called with the split up but otherwise unparsed remainder of the line. This provides all of the information that came with the message, but it's not always the nicest format for the data to be in. For example,JOIN
messages include usernames that include a hostmask, but often the hostmask is irrelevant and only the nickname is desired. SoJOIN
does something that's fairly typical forirc_*
methods: it turns the rough data into something more pleasant to work with and passes the result on touserJoined
:You can see that there's also a conditional here, sometimes it calls
joined
instead ofuserJoined
. This is another example of a transformation from the low-level data into something which is supposed to be more convenient for the application developer to work with.This layering should help you decide which methods to override when handling events. If the highest level callback, such as
userJoined
,joined
, orprivmsg
is sufficient for your requirements, then you should use those because they'll make your task the easiest. On the other hand, if they present the data in an inconvenient format or are awkward to use in some other way, you can drop down to theirc_*
level. Your method will be called instead of the one defined onIRCClient
, so you can handle the data in the lower-level format and the higher level callback won't even be invoked (unless you also invoke the base implementation when you override the method).You'll also find there are IRC messages which
IRCClient
doesn't even define anirc_*
method for. As we saw above in thehandleCommand
method, these all go to theirc_unknown
callback. But if you define anirc_*
method on yourIRCClient
subclass, thenhandleCommand
will start passing the data to that method. Clearly in these cases, your only choice is to define theirc_*
method, since there is no higher-level callback (likeprivmsg
in theirc_PRIVMSG
/privmsg
case).You can structure your implementations of
irc_*
methods similarly to the wayIRCClient
does, if you like - I usually find it helpful to do so, since it makes unit testing easier and keeps the protocol parsing logic separate from the application logic - but it's up to you.