Словарь или If заявления, Jython - PullRequest
4 голосов
/ 10 ноября 2008

Я сейчас пишу скрипт, который будет извлекать определенную информацию из HTML с помощью dom4j.

Так как Python / Jython не имеет собственного оператора switch , я решил использовать целую кучу операторов if , которые вызывают соответствующий метод, как показано ниже:

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

Я буду добавлять больше, в зависимости от того, какую информацию я хочу извлечь из HTML, и подумать о том, чтобы использовать словарный подход, который я нашел в другом месте на этом сайте, пример ниже:

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

Я знаю, что каждый раз, когда я запускаю сценарий, словарь будет создаваться, но в то же время, если бы я использовал операторы , если , сценарию пришлось бы проверять их все, пока он не достигнет правильный. Что мне действительно интересно, какой из них работает лучше или вообще лучше использовать?

Обновление: @Brian - Спасибо за отличный ответ. У меня есть вопрос, если какой-либо из методов извлечения требует более одного объекта, например

handle_extractTag(self, dom, anotherObject)
# Do something

Как бы вы внесли соответствующие изменения в метод handle , чтобы реализовать это? Надеюсь, вы понимаете, о чем я:)

Приветствия

Ответы [ 5 ]

14 голосов
/ 10 ноября 2008

Чтобы избежать указания тега и обработчика в 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)

Обновление:

Если у вас есть несколько аргументов, просто измените функцию handle, чтобы эти аргументы передавались и передавались в функцию. Если вы хотите сделать его более универсальным (чтобы вам не приходилось менять как функции-обработчики, так и метод handle при изменении сигнатуры аргумента), вы можете использовать синтаксис * 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)
2 голосов
/ 10 ноября 2008

С вашим кодом вы запускаете все ваши функции.

handlers = {
'extractTitle': extractTitle, 
'extractMetaTags': extractMetaTags
}

handlers[type](dom)

Будет работать как ваш оригинальный if код.

1 голос
/ 10 ноября 2008

Вопрос эффективности едва уместен. Поиск в словаре выполняется с помощью простой техники хеширования, операторы 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.

1 голос
/ 10 ноября 2008

Ваше использование словаря не совсем корректно. В вашей реализации все методы будут вызваны, а все бесполезные - отброшены. То, что обычно делается, больше похоже на:

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

И этот способ более сложный и расширяемый, если у вас большое (или переменное) количество элементов.

1 голос
/ 10 ноября 2008

Это зависит от того, о скольких утверждениях мы говорим; если это очень маленькое число, то оно будет более эффективным, чем использование словаря.

Однако, как всегда, я настоятельно советую вам делать все, чтобы ваш код выглядел чище, пока опыт и профилирование не скажут вам, что определенный блок кода необходимо оптимизировать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...