4

我现在正在编写一个脚本,它将使用 dom4j 从 HTML 中获取某些信息。

由于 Python/Jython 没有本机switch语句,我决定使用一大堆调用适当方法的if语句,如下所示:

if type == 'extractTitle':
    extractTitle(dom)
if type == 'extractMetaTags':
    extractMetaTags(dom)

我将根据我想从 HTML 中提取的信息添加更多内容,并考虑采用我在本网站其他地方找到的字典方法,示例如下:

{
    'extractTitle':    extractTitle,
    'extractMetaTags': extractMetaTags
}[type](dom)

我知道每次运行脚本时都会构建字典,但与此同时,如果我要使用if语句,脚本必须检查所有这些语句,直到找到正确的语句。我真正想知道的是,哪一个表现更好或通常是更好的做法?

更新: @Brian - 感谢您的精彩回复。我有一个问题,如果任何提取方法需要多个对象,例如

handle_extractTag(self, dom, anotherObject)
# Do something

您将如何对handle方法进行适当的更改来实现这一点?希望你知道我的意思:)

干杯

4

5 回答 5

14

为了避免在 dict 中指定标签和处理程序,您可以只使用一个处理程序类,其中的方法命名为匹配类型。例如

class  MyHandler(object):
    def handle_extractTitle(self, dom):
        # do something

    def handle_extractMetaTags(self, dom):
        # do something

    def handle(self, type, dom):
        func = getattr(self, 'handle_%s' % type, None)
        if func is None:
            raise Exception("No handler for type %r" % type)
        return func(dom)

用法:

 handler = MyHandler()
 handler.handle('extractTitle', dom)

更新:

当您有多个参数时,只需更改句柄函数以获取这些参数并将它们传递给函数。如果您想让它更通用(这样您在更改参数签名时不必同时更改处理程序函数和句柄方法),您可以使用 *args 和 **kwargs 语法来传递所有接收到的参数. 然后handle方法变成:

def handle(self, type, *args, **kwargs):
    func = getattr(self, 'handle_%s' % type, None)
    if func is None:
        raise Exception("No handler for type %r" % type)
    return func(*args, **kwargs)
于 2008-11-10T14:24:04.580 回答
2

使用您的代码,您正在运行您的所有函数都会被调用。

处理程序 = {
“提取标题”:提取标题,
'extractMetaTags':提取MetaTags
}

处理程序[类型](dom)

会像您的原始if代码一样工作。

于 2008-11-10T14:27:44.963 回答
1

这取决于我们正在谈论多少个 if 语句;如果它是一个非常小的数字,那么它会比使用字典更有效。

但是,与往常一样,我强烈建议您做任何使您的代码看起来更干净的事情,直到经验和分析告诉您需要优化特定的代码块。

于 2008-11-10T14:26:14.857 回答
1

您对字典的使用不太正确。在您的实现中,所有方法都将被调用,所有无用的方法都将被丢弃。通常做的更像是:

switch_dict = {'extractTitle': extractTitle, 
               'extractMetaTags': extractMetaTags}
switch_dict[type](dom)

如果您有大量(或可变)项目,那么这种方式更重要且更具可扩展性。

于 2008-11-10T14:27:35.040 回答
1

效率问题几乎无关紧要。字典查找是通过一种简单的散列技术完成的,if 语句必须一次评估一个。字典往往更快。

我建议你实际上有从 DOM 中提取的多态对象。

目前尚不清楚如何type设置,但它确实看起来可能是一系列相关对象,而不是简单的字符串。

class ExtractTitle( object ):
    def process( dom ):
        return something

class ExtractMetaTags( object ):
    def process( dom ):
        return something

您可以这样做,而不是设置 type="extractTitle"。

type= ExtractTitle() # or ExtractMetaTags() or ExtractWhatever()
type.process( dom )

然后,您将不会构建这个特定的字典或 if 语句。

于 2008-11-10T14:36:53.463 回答