2009-08-10 3 views
3

У меня есть скрипт python, который обрабатывает файл по строкам, если строка соответствует регулярному выражению, она вызывает функцию для ее обработки.Нужна помощь в рефакторинге моего скрипта python

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

Благодарим за любую идею. Теперь мой код в конечном итоге, как это:

 
for line in fi.readlines(): 

     result= reg1.match(line) 

     if result: 
       handleReg1(result) 

     else: 
       result = reg2.match(line) 

       if result: 
         handleReg2(result) 
       else: 
         result = reg3.match(line) 

         if result: 
           handleReg3(result) 
         else: 
           result = reg4.match(line) 

           if result: 
             handleReg4(result) 
           else: 
             result = reg5.match(line) 

             if result: 
               handleReg5(result) 
+4

Любая причина, по которой вы избегаете elif? – balpha

ответ

12

Я бы переключиться на использование структуру данных регулярных выражений отображения для функций. Что-то вроде:

map = { reg1: handleReg1, reg2: handleReg2, etc } 

Тогда вы просто цикл через них:

for reg, handler in map.items(): 
    result = reg.match(line) 
    if result: 
     handler(result) 
     break 

Если вам нужны спички, чтобы произойти в определенном порядке, вы должны будете использовать список вместо словаря, но Принцип один и тот же.

+0

Это тот подход, который я бы рекомендовал. Как упоминалось выше, вы хотите использовать список, если вам нужен определенный порядок - возможно, что-то вроде 'handlers = [(reg1, handleReg1), (reg2, handleReg2), ...]', и тогда ваш цикл for будет выглядеть например: 'for (reg, handler) в обработчиках:' – Amber

+1

Вы определенно хотите список, а не словарь. Здесь нет ключевого поиска - это просто связь между регулярным выражением и функцией. Список кортежей был бы хорош. – hughdbrown

1

Вот тривиальный:

handlers = { reg1 : handleReg1, ... } 

for line in fi.readlines(): 
    for h in handlers: 
     x = h.match(line) 
     if x: 
      handlers[h](x) 

Если может быть линия, которая соответствует нескольким регэкспы этот код будет отличаться от кода, который вы вставили: он будет вызывать несколько обработчиков. Добавление break не поможет, потому что регулярные выражения будут проверяться в другом порядке, поэтому вы в конечном итоге вызываете неправильный. Так что, если это так, вы должны перебрать список:

handlers = [ (reg1, handleReg1), (reg2, handleReg2), ... ] 

for line in fi.readlines(): 
    for reg, handler in handlers: 
     x = reg.match(line) 
     if x: 
      handler(x) 
      break 
+0

Это не идентично; ваш путь может вызвать несколько обработчиков; его звонки не более одного. – balpha

+0

Версия выше не идентична, так как она может попробовать регулярные выражения в порядке, отличном от reg1, reg2, ... –

0

Альтернативный подход, который может работать для вас, чтобы объединить все регулярные выражения в одно гигантское регулярное выражение и использовать m.group(), чтобы определить, какой соответствует. Моя интуиция говорит, что это должно быть быстрее, но я его не тестировал.

>>> reg = re.compile('(cat)|(dog)|(apple)') 
>>> m = reg.search('we like dogs') 
>>> print m.group() 
dog 
>>> print m.groups() 
(None, 'dog', None) 

Это осложняется, если регулярные выражения, которые вы тестируете, сами сложны или используют группы соответствия.

+0

Это очень быстро, и средство против внутренних регулярных выражений, которые являются сложными и используют сопоставимые группы, - это использовать именованные группы вокруг них (в «пространстве имен», например, с префиксом, dijoint из любых именованных групп, которые могут использоваться внутренними регулярными выражениями). –

Смежные вопросы