Question Remplacements pour l'instruction switch en Python?


Je veux écrire une fonction en Python qui renvoie différentes valeurs fixes basées sur la valeur d'un index d'entrée.

Dans d'autres langues, j'utiliserais un switch ou case déclaration, mais Python ne semble pas avoir un switch déclaration. Quelles sont les solutions Python recommandées dans ce scénario?


1440
2017-09-13 00:36


origine


Réponses:


Vous pouvez utiliser un dictionnaire:

def f(x):
    return {
        'a': 1,
        'b': 2,
    }[x]

1125
2017-09-13 00:38



Si vous souhaitez par défaut, vous pouvez utiliser le dictionnaire get(key[, default]) méthode:

def f(x):
    return {
        'a': 1,
        'b': 2
    }.get(x, 9)    # 9 is default if x not found

1108
2017-09-19 15:45



J'ai toujours aimé le faire de cette façon

result = {
  'a': lambda x: x * 5,
  'b': lambda x: x + 7,
  'c': lambda x: x - 2
}[value](x)

D'ici


293
2017-09-13 00:41



En plus des méthodes de dictionnaire (que j'aime vraiment, BTW), vous pouvez aussi utiliser if-elif-else pour obtenir la fonctionnalité switch / case / default:

if x == 'a':
    # Do the thing
elif x == 'b':
    # Do the other thing
if x in 'bc':
    # Fall-through by not using elif, but now the default case includes case 'a'!
elif x in 'xyz':
    # Do yet another thing
else:
    # Do the default

Bien sûr, ce n'est pas identique à switch / case - vous ne pouvez pas avoir une chute aussi facilement que de quitter la pause; déclaration, mais vous pouvez avoir un test plus compliqué. Sa mise en forme est plus agréable qu'une série d'ifs imbriqués, même si fonctionnellement c'est ce dont il est plus proche.


248
2017-09-13 01:10



Ma recette préférée de Python pour switch / case est:

choices = {'a': 1, 'b': 2}
result = choices.get(key, 'default')

Court et simple pour des scénarios simples.

Comparez à 11+ lignes de code C:

// C Language version of a simple 'switch/case'.
switch( key ) 
{
    case 'a' :
        result = 1;
        break;
    case 'b' :
        result = 2;
        break;
    default :
        result = -1;
}

Vous pouvez même assigner plusieurs variables en utilisant des tuples:

choices = {'a': (1, 2, 3), 'b': (4, 5, 6)}
(result1, result2, result3) = choices.get(key, ('default1', 'default2', 'default3'))

122
2018-06-17 02:25



class switch(object):
    value = None
    def __new__(class_, value):
        class_.value = value
        return True

def case(*args):
    return any((arg == switch.value for arg in args))

Usage:

while switch(n):
    if case(0):
        print "You typed zero."
        break
    if case(1, 4, 9):
        print "n is a perfect square."
        break
    if case(2):
        print "n is an even number."
    if case(2, 3, 5, 7):
        print "n is a prime number."
        break
    if case(6, 8):
        print "n is an even number."
        break
    print "Only single-digit numbers are allowed."
    break

Tests:

n = 2
#Result:
#n is an even number.
#n is a prime number.
n = 11
#Result:
#Only single-digit numbers are allowed.

85
2017-07-07 06:09



Il y a un motif que j'ai appris du code Twisted Python.

class SMTP:
    def lookupMethod(self, command):
        return getattr(self, 'do_' + command.upper(), None)
    def do_HELO(self, rest):
        return 'Howdy ' + rest
    def do_QUIT(self, rest):
        return 'Bye'

SMTP().lookupMethod('HELO')('foo.bar.com') # => 'Howdy foo.bar.com'
SMTP().lookupMethod('QUIT')('') # => 'Bye'

Vous pouvez l'utiliser chaque fois que vous avez besoin d'envoyer un jeton et d'exécuter un morceau de code étendu. Dans une machine d'état, vous auriez state_ méthodes, et expédier sur self.state. Ce changement peut être proprement étendu en héritant de la classe de base et en définissant votre propre do_ méthodes Souvent, vous n'aurez même pas do_ méthodes dans la classe de base.

Edit: comment exactement est-ce utilisé

En cas de SMTP, vous recevrez HELO du fil. Le code pertinent (de twisted/mail/smtp.py, modifié pour notre cas) ressemble à ceci

class SMTP:
    # ...

    def do_UNKNOWN(self, rest):
        raise NotImplementedError, 'received unknown command'

    def state_COMMAND(self, line):
        line = line.strip()
        parts = line.split(None, 1)
        if parts:
            method = self.lookupMethod(parts[0]) or self.do_UNKNOWN
            if len(parts) == 2:
                return method(parts[1])
            else:
                return method('')
        else:
            raise SyntaxError, 'bad syntax'

SMTP().state_COMMAND('   HELO   foo.bar.com  ') # => Howdy foo.bar.com

Tu recevras ' HELO foo.bar.com ' (ou vous pourriez obtenir 'QUIT' ou 'RCPT TO: foo'). Ceci est tokenized en parts comme ['HELO', 'foo.bar.com']. Le nom de référence de la méthode réelle provient de parts[0].

(La méthode originale est également appelée state_COMMAND, car il utilise le même modèle pour implémenter une machine d'état, c'est-à-dire getattr(self, 'state_' + self.mode))


41
2017-09-13 01:26