J'ai une instruction in if-elif-elif-else dans laquelle 99% du temps, l'instruction else est exécutée:
if something == 'this':
doThis()
elif something == 'that':
doThat()
elif something == 'there':
doThere()
else:
doThisMostOfTheTime()
Cette construction est beaucoup faite , mais comme elle passe en revue toutes les conditions avant qu'elle ne touche l'autre, j'ai le sentiment que ce n'est pas très efficace, encore moins Pythonic. D'un autre côté, il a besoin de savoir si l'une de ces conditions est remplie, il devrait donc le tester de toute façon.
Est-ce que quelqu'un sait si et comment cela pourrait être fait plus efficacement ou est-ce simplement la meilleure façon de le faire?
python
performance
if-statement
kramer65
la source
la source
sort
les choses sur lesquelles vous exécutez votre chaîne if / else ..., de telle sorte que tous les éléments auxquels l'une des conditions correspondra soient à une extrémité et tous les autres à l'autre? Si c'est le cas, vous pouvez voir si c'est plus rapide / plus élégant ou non. Mais rappelez-vous, s'il n'y a pas de problème de performances, il est trop tôt pour s'inquiéter de l'optimisation.if not something.startswith("th"): doThisMostOfTheTime()
et faire une autre comparaison dans laelse
clause.something
, ou des comparaisons similaires sont-elles effectuées plusieurs fois sur la même valeur?Réponses:
Le code...
... semble devoir être plus rapide, mais il est en fait plus lent que la construction
if
...elif
...else
, car il doit appeler une fonction, ce qui peut être une surcharge de performances significative dans une boucle serrée.Considérez ces exemples ...
1.py
2.py
3.py
4.py
... et notez la quantité de temps CPU qu'ils utilisent ...
... en utilisant le temps utilisateur de
time(1)
.L'option n ° 4 a la surcharge de mémoire supplémentaire liée à l'ajout d'un nouvel élément pour chaque clé manquante distincte, donc si vous vous attendez à un nombre illimité de clés manquées distinctes, j'irais avec l'option n ° 3, qui est toujours une amélioration significative sur la construction originale.
la source
dict
est plus lente, mais votre minutage montre en fait que c'est la deuxième option la plus rapide.dict.get()
c'est plus lent, qui est2.py
- le plus lent de tous.Je créerais un dictionnaire:
Maintenant, utilisez simplement:
Si
something
n'est pas trouvé dans leoptions
dict alorsdict.get
retournera la valeur par défautdoThisMostOfTheTime
Quelques comparaisons de temps:
Scénario:
Résultats:
Pour
10**5
les clés inexistantes et 100 clés valides:Donc, pour un dictionnaire normal, vérifier la clé en utilisant
key in options
est le moyen le plus efficace ici:la source
options = collections.defaultdict(lambda: doThisMostOfTheTime, {'this': doThis,'that' :doThat, 'there':doThere}); options[something]()
est légèrement plus efficace.options
dict pour éviter de le reconstruire, déplaçant ainsi une partie (mais pas la totalité) de la logique loin du point d'utilisation. Encore, belle astuce!try: options[key]() except KeyError: doSomeThingElse()
(car avecif key in options: options[key]()
vous recherchez le dictionnaire deux fois pourkey
Pouvez-vous utiliser pypy?
Garder votre code d'origine mais l'exécuter sur pypy me donne une accélération de 50x.
CPython:
Pypy:
la source
Voici un exemple de if avec des conditions dynamiques traduites dans un dictionnaire.
C'est un moyen, mais ce n'est peut-être pas le moyen le plus pythonique de le faire car il est moins lisible pour qui ne parle pas couramment Python.
la source
Les gens mettent en garde
exec
pour des raisons de sécurité, mais c'est un cas idéal pour cela.C'est une machine à états facile.
la source