110 votes

La manière la plus efficace de faire une déclaration if-elif-elif-else lorsque le else est le plus utilisé ?

J'ai une instruction if-elif-elif-else dans laquelle, dans 99 % des cas, l'instruction else est exécutée :

if something == 'this':
    doThis()
elif something == 'that':
    doThat()
elif something == 'there':
    doThere()
else:
    doThisMostOfTheTime()

Cette construction se fait beaucoup mais comme il passe en revue chaque condition avant d'atteindre l'autre, j'ai l'impression que ce n'est pas très efficace, et encore moins pythonique. D'un autre côté, il a besoin de savoir si l'une de ces conditions est remplie, donc il devrait quand même la tester.

Quelqu'un sait-il si et comment cela pourrait être fait plus efficacement ou est-ce simplement la meilleure façon de procéder ?

0 votes

Pouvez-vous sort les éléments sur lesquels vous exécutez votre chaîne if/else..., de sorte que tous les éléments pour lesquels l'une des conditions correspondra se trouvent à une extrémité, et tous les autres à l'autre ? Si c'est le cas, vous pourriez voir si cela est plus rapide/plus élégant ou non. Mais rappelez-vous, s'il n'y a pas de problème de performance, il est trop tôt pour se préoccuper de l'optimisation.

1 votes

0 votes

@Patashu - Malheureusement, j'ai un énorme problème de performance. Ce programme fonctionne jour et nuit en analysant d'énormes quantités de données. C'est seulement parce que mes compétences en C++ ne sont pas à la hauteur (et j'adore Python) que je ne le réécris pas

0voto

Saurav Points 77

Récemment, j'ai découvert une approche alternative aux "if else imbriqués" qui réduit le temps d'exécution de ma fonction de 2,5 heures à ~2 minutes Baam ! Commençons :

Code antérieur
bin = lambda x : "Unknown" if x==0 else("High" if x>75 else("Medium" if x>50 and x<=75 else("Medium_Low" if x>25 and x<=50 else "Low")))

col.apply(bin) Durée ~2,5 heures

Optimiser le code

Définir Dictionnaire alternative à nid si else

 def dict_function(*args):
'Pass in a list of tuples, which will be key/value pairs'
ret = {}
for k,v in args:
    for i in k:
        ret[i] = v
return ret
Dict = dict_function(([0],"Unknown"),(range(1,25),"Low"),(range(25,50),"Medium_Low"),(range(50,75),"Medium"),(range(75,100),"High"))

col.apply(lambda x:Dict[x])

La fonction dict_fonction crée plusieurs paires clé-valeur pour une plage donnée. Temps~2mins

0voto

Tw UxTLi51Nus Points 852

J'ai eu le même problème récemment, bien que ne concernant pas les performances, mais je n'aime pas l'"API" consistant à créer des fonctions et à les ajouter manuellement à un dict. Je voulais une API similaire à functools.singledispatch mais pour répartir sur la base des valeurs et non des types. Donc...

def value_dispatch(func):
    """value-dispatch function decorator.
    Transforms a function into a function, that dispatches its calls based on the
    value of the first argument.
    """
    funcname = getattr(func, '__name__')
    registry = {}

    def dispatch(arg):
        """return the function that matches the argument"""
        return registry.get(arg, func)

    def register(arg):
        def wrapper(func):
            """register a function"""
            registry[arg] = func
            return func
        return wrapper

    def wrapper(*args, **kwargs):
        if not args:
            raise ValueError(f'{funcname} requires at least 1 positional argument')
        return dispatch(args[0])(*args, **kwargs)

    wrapper.register = register
    wrapper.dispatch = dispatch
    wrapper.registry = registry
    return wrapper

Utilisez comme ça :

@value_dispatch
def handle_something():
    print("default")

@handle_something.register(1)
def handle_one():
    print("one")

handle_something(1)
handle_something(2)

PS : J'ai créé un extrait sur Gitlab pour référence

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X