2009-08-10 10 views
3

J'ai un script python qui traite un fichier ligne par ligne, si la ligne correspond à une regex, elle appelle une fonction pour le gérer.Besoin d'aide pour refactoriser mon script python

Ma question est là est une meilleure écriture pour refactoriser mon script. Le script fonctionne, mais comme il est, je dois garder l'indentation à la droite de l'éditeur car j'ajoute de plus en plus de regex pour mon fichier.

Merci pour votre idée. Maintenant, mon code finiras comme ceci:

 
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

Pour quelle raison évitez-vous elif? – balpha

Répondre

12

je aimerais passer à l'aide d'un regexes de cartographie de la structure de données aux fonctions. Quelque chose comme:

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

Alors vous venez de boucle à travers eux:

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

Si vous avez besoin des matches pour arriver dans un ordre particulier, vous aurez besoin d'utiliser une liste au lieu d'un dictionnaire, mais le le principal est le même.

+0

C'est l'approche que je recommanderais également. Comme sam mentionné, vous voudrez utiliser une liste si vous avez besoin d'un certain ordre - probablement quelque chose comme 'handlers = [(reg1, handleReg1), (reg2, handleReg2), ...]' et votre boucle for ressemblerait comme ceci: 'for (reg, handler) dans les gestionnaires:' – Amber

+1

Vous voulez certainement une liste et pas un dictionnaire. Il n'y a pas de recherche de clé ici - c'est juste une association entre une regex et une fonction. Une liste de tuples serait bonne. – hughdbrown

1

est ici triviale:

handlers = { reg1 : handleReg1, ... } 

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

S'il pourrait y avoir une ligne qui correspond à plusieurs regexps ce code sera différent du code que vous avez collé: il appellera plusieurs gestionnaires. L'ajout de break n'aidera pas, car les expressions rationnelles seront essayées dans un ordre différent, donc vous finirez par appeler le mauvais. Donc, si tel est le cas, vous devez itérer sur la liste:

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

Ce n'est pas identique. votre chemin pourrait appeler plusieurs gestionnaires; ses appels au plus un. – balpha

+0

La version ci-dessus n'est pas identique non plus car elle peut essayer des expressions rationnelles différentes de reg1, reg2, ... –

0

Une autre approche qui pourrait fonctionner pour vous est de combiner toutes les expressions régulières dans un regexp géant et de détecter ce qui correspond utiliser m.group(). Mon intuition dit que cela devrait être plus rapide, mais je ne l'ai pas testé.

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

Cela devient compliqué si les expressions rationnelles que vous testez sont elles-mêmes compliquées ou utilisent des groupes de correspondance.

+0

C'est très rapide, et le remède contre les expressions rationnelles internes qui utilisent des groupes de correspondance est d'utiliser des groupes nommés autour d'elles (dans un "namespace", par exemple w/un préfixe, dijoint de tous les groupes nommés qui peuvent être utilisés par les expressions rationnelles internes). –

Questions connexes