2010-01-11 7 views
2

J'ai ce morceau de code (doit être explicite, sinon, il suffit de demander):Quel est le moyen Pythonic pour l'écriture algorithme de correspondance

for tr in completed_taskrevs: 
    found = False 
    for nr in completion_noterevs: 
     if tr.description in nr.body: 
      completion_noterevs.remove(nr) 
      found = True 
      break 
    assert found 

Comment puis-je le rendre plus pythonique?

+3

Que signifie "algo"? –

+0

@ Algorithme S.Lott. –

+0

@Hank Gay: Vraiment? Quelle langue est-ce? –

Répondre

6

En utilisant assert/AssertionError est probablement mal ici, je dirais. C'est utile pour "debugging assertions", c'est-à-dire, pour vous assurer que votre code est sain. Il n'est pas utile pour générer une erreur lorsque vous obtenez des données invalides, pour plusieurs raisons, dont la plus intéressante est probablement que l'assertion n'est même pas garantie d'être exécutée - si votre code est compilé avec des paramètres d'optimisation, il ne sera pas. Et diable, même si c'est un truc de débogage, j'utiliserais toujours raise-- c'est plus lisible, et ça arrivera toujours, peu importe quand ou pourquoi les données sont fausses. Donc pour le rendre plus "pythonique", je supprimerais l'affirmer et le remplacerais par quelque chose de plus agréable. En l'occurrence, une chose plus belle existe, et c'est l'instruction raise. De plus, je remplacerais l'ensemble de valeurs maladroites/vérifier avec le else clause of loops, qui est exécuté lorsque la boucle est épuisée (ou, pour les boucles while, lorsque la condition devient fausse). Donc, si vous cassez, la clause else n'est pas exécutée.

for tr in completed_taskrevs: 
    for nr in completion_noterevs: 
     if tr.description in nr.body: 
      completion_noterevs.remove(nr) 
      break 
    else: 
     raise ValueError("description not found"); # or whatever exception would be appropriate 

À part cela, je ne changerais probablement rien.

+0

Ce 'else' est très bien, je ne le savais pas. En ce qui concerne l'assertion - l'extrait de code provient d'un outil piraté rapidement, et non d'un code de production, donc pour moi (et mon client), il est parfaitement acceptable d'utiliser l'assertion. –

8

Essayez ceci:

for tr in compleded_taskrevs: 
    try: 
     nrs = (nr for nr in completion_noterevs if tr.description in nr.body) 
     completion_noterevs.remove(nrs.next()) 
    except StopIteration: 
     raise ValueError('Some error') 

EDIT: Devin est juste. L'assertion n'est pas la solution, mieux vaut utiliser une exception standard.

+0

Merci. Il ressemble probablement le plus à Pythonic, mais ce n'est pas évident pour moi à première vue. C'est pourquoi je vote maintenant pour votre réponse mais j'accepte celle de Devin. –

3

Le générateur de liste ci-dessous peut vous renvoyer tous les éléments qui sont valides tr.description in nr.body mais il est difficile de simplifier votre algorithme car il a quelques branches. Je dirais juste aller avec l'algorithme que vous avez aussi longtemps qu'il fait ce que vous voulez.

[nr for tr in completed_taskrevs for nr in completion_noterevs if tr.description in nr.body] 
+0

Cela semble également Pythonic, mais il est trop obfusqué pour moi. Je préfère le code Pythonic et le code facilement lisible. En écrivant ceci, votez pour vous. –

+0

Ouais, je suis d'accord avec le peu d'obfuscation. Il faut toujours chercher l'équilibre. – rui

Questions connexes