Des remplacements pour l'instruction switch en Python?

je veux écrire une fonction Python qui retourne différentes valeurs fixes basés sur la valeur d'une entrée d'index.

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

1524
demandé sur codeforester 2008-09-13 04:36:30

30 réponses

vous pouvez utiliser un dictionnaire:

def f(x):
    return {
        'a': 1,
        'b': 2,
    }[x]
1184
répondu Greg Hewgill 2008-09-13 00:38:24

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
1155
répondu Nick 2017-07-06 22:51:30

j'ai toujours aimé faire comme ça

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

D'ici

312
répondu Mark Biek 2014-02-16 05:06:42

en plus des méthodes du dictionnaire (que j'aime vraiment, BTW), vous pouvez également 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

ce n'est évidemment pas identique à switch/case - vous ne pouvez pas avoir la chute-à travers aussi facilement que de laisser tomber la pause; déclaration, mais vous pouvez avoir un test plus compliqué. Son formatage est plus agréable qu'une série d'ifs imbriqués, même si c'est fonctionnellement ce qu'il est le plus proche.

258
répondu Matthew Schinckel 2015-06-10 14:07:33

ma recette Python préférée 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 du 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 tuples:

choices = {'a': (1, 2, 3), 'b': (4, 5, 6)}
(result1, result2, result3) = choices.get(key, ('default1', 'default2', 'default3'))
134
répondu ChaimG 2015-08-16 21:58:26
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))

Utilisation:

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

Essais:

n = 2
#Result:
#n is an even number.
#n is a prime number.
n = 11
#Result:
#Only single-digit numbers are allowed.
87
répondu adamh 2013-05-31 14:24:52

il y a un modèle que j'ai appris du code Python tordu.

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 sur un token et d'exécuter un morceau de code étendu. Dans une machine d'état, vous auriez les méthodes state_ , et l'expédition sur self.state . Ce commutateur peut être proprement étendu en héritant de la classe de base et en définissant vos propres méthodes do_ . Souvent, vous n'aurez même pas les méthodes do_ dans la classe de base.

Edit: comment exactement Est-ce utilisé

en cas de SMTP vous recevrez HELO du fil. Le code correspondant (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

Vous recevrez ' 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 la recherche de méthode actuelle est tiré de parts[0] .

(la méthode originale est également appelée state_COMMAND , parce qu'elle utilise le même modèle pour mettre en œuvre une machine d'état, i.e. getattr(self, 'state_' + self.mode) )

42
répondu 2008-09-13 17:42:03

mon préféré est un très bon recette . Vous aimerez vraiment. C'est le plus proche que j'ai vu des déclarations de cas réels de changement, en particulier dans les fonctionnalités.

voici un exemple:

# The following example is pretty much the exact use-case of a dictionary,
# but is included for its simplicity. Note that you can include statements
# in each suite.
v = 'ten'
for case in switch(v):
    if case('one'):
        print 1
        break
    if case('two'):
        print 2
        break
    if case('ten'):
        print 10
        break
    if case('eleven'):
        print 11
        break
    if case(): # default, could also just omit condition or 'if True'
        print "something else!"
        # No need to break here, it'll stop anyway

# break is used here to look as much like the real thing as possible, but
# elif is generally just as good and more concise.

# Empty suites are considered syntax errors, so intentional fall-throughs
# should contain 'pass'
c = 'z'
for case in switch(c):
    if case('a'): pass # only necessary if the rest of the suite is empty
    if case('b'): pass
    # ...
    if case('y'): pass
    if case('z'):
        print "c is lowercase!"
        break
    if case('A'): pass
    # ...
    if case('Z'):
        print "c is uppercase!"
        break
    if case(): # default
        print "I dunno what c was!"

# As suggested by Pierre Quentel, you can even expand upon the
# functionality of the classic 'case' statement by matching multiple
# cases in a single shot. This greatly benefits operations such as the
# uppercase/lowercase example above:
import string
c = 'A'
for case in switch(c):
    if case(*string.lowercase): # note the * for unpacking as arguments
        print "c is lowercase!"
        break
    if case(*string.uppercase):
        print "c is uppercase!"
        break
    if case('!', '?', '.'): # normal argument passing style also applies
        print "c is a sentence terminator!"
        break
    if case(): # default
        print "I dunno what c was!"
38
répondu John Doe 2011-07-07 06:12:47
class Switch:
    def __init__(self, value): self._val = value
    def __enter__(self): return self
    def __exit__(self, type, value, traceback): return False # Allows traceback to occur
    def __call__(self, *mconds): return self._val in mconds

from datetime import datetime
with Switch(datetime.today().weekday()) as case:
    if case(0):
        # Basic usage of switch
        print("I hate mondays so much.")
        # Note there is no break needed here
    elif case(1,2):
        # This switch also supports multiple conditions (in one line)
        print("When is the weekend going to be here?")
    elif case(3,4): print("The weekend is near.")
    else:
        # Default would occur here
        print("Let's go have fun!") # Didn't use case for example purposes
30
répondu Ian Bell 2017-12-15 20:25:07

disons que vous ne voulez pas simplement retourner une valeur, mais que vous voulez utiliser des méthodes qui changent quelque chose sur un objet. En utilisant l'approche énoncée ici serait:

result = {
  'a': obj.increment(x),
  'b': obj.decrement(x)
}.get(value, obj.default(x))

ce qui se passe ici est que python évalue toutes les méthodes dans le dictionnaire. Donc, même si votre valeur est 'a', l'objet sera incrémentée et décrémenté par x.

Solution:

func, args = {
  'a' : (obj.increment, (x,)),
  'b' : (obj.decrement, (x,)),
}.get(value, (obj.default, (x,)))

result = func(*args)

Donc, vous obtenez une liste contenant une fonction et ses arguments. De cette façon, seulement le pointeur de fonction et la liste d'arguments sont retournés, pas évalué. 'result' évalue alors l'appel de fonction retourné.

23
répondu GeeF 2010-09-30 08:31:55

je vais juste laisser tomber mes deux cents ici. La raison pour laquelle il n'y a pas d'instruction case/switch en Python est que Python suit le principe de 'Theres only one right way to do something'. Donc évidemment, vous pouvez trouver différentes façons de recréer la fonctionnalité switch/case, mais la façon pythonique d'accomplir ceci est la construction if/elif. c'est à dire

if something:
    return "first thing"
elif somethingelse:
    return "second thing"
elif yetanotherthing:
    return "third thing"
else:
    return "default thing"

J'ai juste senti que PEP 8 méritait un clin d'œil ICI. Une des belles choses au sujet de Python est son la simplicité et l'élégance. Cela découle en grande partie des principes énoncés dans la PEP 8, y compris "il n'y a qu'une seule bonne façon de faire quelque chose "

15
répondu user2233949 2017-08-14 22:19:38

développement de l'idée" dict as switch". si vous souhaitez utiliser une valeur par défaut pour votre switch:

def f(x):
    try:
        return {
            'a': 1,
            'b': 2,
        }[x]
    except KeyError:
        return 'default'
13
répondu Jeremy Cantrell 2008-09-19 15:37:15

si vous avez un bloc de cas compliqué, vous pouvez envisager d'utiliser une table de recherche de dictionnaire de fonction...

si vous n'avez pas fait cela avant son une bonne idée d'entrer dans votre débogueur et de voir exactement comment le dictionnaire regarde chaque fonction.

REMARQUE: Ne pas utilisation "()" à l'intérieur du boîtier/recherche dans le dictionnaire ou il va appeler chacun de vos fonctions, dictionnaire de cas et de bloc est créé. Rappelez-vous ce parce que vous je veux seulement appeler chaque fonction une fois en utilisant une recherche de style de hachage.

def first_case():
    print "first"

def second_case():
    print "second"

def third_case():
    print "third"

mycase = {
'first': first_case, #do not use ()
'second': second_case, #do not use ()
'third': third_case #do not use ()
}
myfunc = mycase['first']
myfunc()
13
répondu htmlfarmer 2012-10-17 21:52:45

si vous recherchez une déclaration supplémentaire, comme" switch", j'ai construit un module python qui étend Python. Il s'appelle ESPY comme "structure améliorée pour Python" et il est disponible pour les deux Python 2.x et Python 3.x.

par exemple, dans ce cas, une instruction de commutation pourrait être exécutée avec le code suivant:

macro switch(arg1):
    while True:
        cont=False
        val=%arg1%
        socket case(arg2):
            if val==%arg2% or cont:
                cont=True
                socket
        socket else:
            socket
        break

qui peut être utilisé comme ceci:

a=3
switch(a):
    case(0):
        print("Zero")
    case(1):
        print("Smaller than 2"):
        break
    else:
        print ("greater than 1")

ainsi espy traduire en Python as:

a=3
while True:
    cont=False
    if a==0 or cont:
        cont=True
        print ("Zero")
    if a==1 or cont:
        cont=True
        print ("Smaller than 2")
        break
    print ("greater than 1")
    break
13
répondu elp 2018-08-28 15:09:16

Je n'ai pas trouvé la réponse simple que je cherchais n'importe où sur Google search. Mais j'ai tout compris de toute façon. C'est vraiment très simple. Décidé de le poster, et peut-être éviter quelques rayures sur quelqu'un d'autre de sa tête. La clé est simplement " in " et tuples. Voici le comportement de la déclaration de commutateur avec la chute-à travers, y compris la chute aléatoire à travers.

l = ['Dog', 'Cat', 'Bird', 'Bigfoot',
     'Dragonfly', 'Snake', 'Bat', 'Loch Ness Monster']

for x in l:
    if x in ('Dog', 'Cat'):
        x += " has four legs"
    elif x in ('Bat', 'Bird', 'Dragonfly'):
        x += " has wings."
    elif x in ('Snake',):
        x += " has a forked tongue."
    else:
        x += " is a big mystery by default."
    print(x)

print()

for x in range(10):
    if x in (0, 1):
        x = "Values 0 and 1 caught here."
    elif x in (2,):
        x = "Value 2 caught here."
    elif x in (3, 7, 8):
        x = "Values 3, 7, 8 caught here."
    elif x in (4, 6):
        x = "Values 4 and 6 caught here"
    else:
        x = "Values 5 and 9 caught in default."
    print(x)

, dispose: "les 151930920"

Dog has four legs
Cat has four legs
Bird has wings.
Bigfoot is a big mystery by default.
Dragonfly has wings.
Snake has a forked tongue.
Bat has wings.
Loch Ness Monster is a big mystery by default.

Values 0 and 1 caught here.
Values 0 and 1 caught here.
Value 2 caught here.
Values 3, 7, 8 caught here.
Values 4 and 6 caught here
Values 5 and 9 caught in default.
Values 4 and 6 caught here
Values 3, 7, 8 caught here.
Values 3, 7, 8 caught here.
Values 5 and 9 caught in default.
12
répondu JD Graham 2013-10-12 18:43:57

j'ai trouvé qu'une structure de commutateur commune:

switch ...parameter...
case p1: v1; break;
case p2: v2; break;
default: v3;

peut être exprimé en Python comme suit:

(lambda x: v1 if p1(x) else v2 if p2(x) else v3)

ou la mise en forme d'une façon plus claire:

(lambda x:
     v1 if p1(x) else
     v2 if p2(x) else
     v3)

au lieu d'être une instruction, la version python est une expression, qui s'évalue à une valeur.

12
répondu leo 2015-05-29 17:25:57

les solutions que j'utilise:

une combinaison de 2 des solutions affichées ici, qui est relativement facile à lire et prend en charge par défaut.

result = {
  'a': lambda x: x * 5,
  'b': lambda x: x + 7,
  'c': lambda x: x - 2
}.get(whatToUse, lambda x: x - 22)(value)

.get('c', lambda x: x - 22)(23)

cherche "lambda x: x - 2" dans le dict et l'utilise avec x=23

.get('xxx', lambda x: x - 22)(44)

ne le trouve pas dans le dict et utilise la valeur par défaut "lambda x: x - 22" avec x=44 .

10
répondu thomasf1 2012-02-23 16:27:48
# simple case alternative

some_value = 5.0

# this while loop block simulates a case block

# case
while True:

    # case 1
    if some_value > 5:
        print ('Greater than five')
        break

    # case 2
    if some_value == 5:
        print ('Equal to five')
        break

    # else case 3
    print ( 'Must be less than 5')
    break
8
répondu user5224656 2015-10-24 01:17:46

j'ai fait une solution (relativement) flexible et réutilisable pour cela. Il peut être trouvé à GitHub comme ce gist . Si le résultat de la fonction de commutation est remboursable, il est automatiquement appelé.

6
répondu 2009-06-05 14:20:52

j'ai aimé Marque Bies la réponse de

étant donné que la variable x doit être utilisée deux fois, j'ai modifié les fonctions lambda pour paramétrerless.

je dois courir avec results[value](value)

In [2]: result = {
    ...:   'a': lambda x: 'A',
    ...:   'b': lambda x: 'B',
    ...:   'c': lambda x: 'C'
    ...: }
    ...: result['a']('a')
    ...: 
Out[2]: 'A'

In [3]: result = {
    ...:   'a': lambda : 'A',
    ...:   'b': lambda : 'B',
    ...:   'c': lambda : 'C',
    ...:   None: lambda : 'Nothing else matters'

    ...: }
    ...: result['a']()
    ...: 
Out[3]: 'A'

Edit: j'ai remarqué que je peux utiliser None avec à l'aide de dictionnaires. Donc, ceci émule switch ; case else

6
répondu guneysus 2017-05-23 11:47:36

la plupart des réponses ici sont assez anciennes, et surtout celles acceptées, il semble donc intéressant de les mettre à jour.

tout d'abord, l'officiel Python FAQ couvre ceci, et recommande la chaîne elif pour les cas simples et le dict pour les cas plus grands ou plus complexes. Il suggère également un ensemble de méthodes visit_ (un style utilisé par de nombreux cadres de serveur) pour certains cas:

def dispatch(self, value):
    method_name = 'visit_' + str(value)
    method = getattr(self, method_name)
    method()

la FAQ mentionne aussi PEP 275 , qui a été écrit pour obtenir une décision officielle Une fois pour toutes sur l'ajout de déclarations de commutateur de style C. Mais cette PEP a été en fait reportée à Python 3, et il a été officiellement rejeté comme une proposition distincte, PEP 3103 . La réponse était, bien sûr, non-mais les deux PEP ont des liens vers des informations supplémentaires si vous êtes intéressé par les raisons ou l'histoire.


une chose qui est venue plusieurs fois (et peut être vu dans PEP 275, même si il a été découpé comme une recommandation réelle) est que si vous êtes vraiment ennuyé par avoir 8 lignes de code pour gérer 4 cas, par rapport aux 6 lignes que vous auriez en C ou Bash, vous pouvez toujours écrire ceci:

if x == 1: print('first')
elif x == 2: print('second')
elif x == 3: print('third')
else: print('did not place')

ce N'est pas exactement encouragé par PEP 8, mais c'est lisible et pas trop unidiomatique.


Les énoncés de cas de style C, ou même la version légèrement plus puissante de Go, ont été considérés comme morts; chaque fois que quelqu'un en parle sur python-ideas ou-dev, ils sont référés à l'ancienne décision.

cependant, l'idée D'une correspondance complète des motifs de style ML apparaît à intervalles de quelques années, d'autant plus que des langues comme Swift et Rust l'ont adoptée. Le problème est qu'il est difficile d'obtenir beaucoup d'utilisation hors de l'appariement de modèle sans types de données algébriques. Alors que Guido a été sympathique à l'idée, personne n'est venu avec une proposition qui s'inscrit dans Python très bien. (Vous pouvez lire mon 2014 strawman pour un exemple.) Ceci pourrait changer avec dataclass en 3.7 et quelques propositions sporadiques pour un enum plus puissant pour traiter les types de Somme, ou avec diverses propositions pour différents types de déclaration-les fixations locales (comme PEP 3150 , ou l'ensemble des propositions actuellement discutées sur-Idées). Mais jusqu'à présent, non.

il y a aussi à l'occasion des propositions pour L'appariement Perl 6-style, qui est essentiellement un méli-mélo de tout de elif à la regex à la commutation de type de répartition simple.

6
répondu abarnert 2018-04-10 06:13:39
def f(x):
     return 1 if x == 'a' else\
            2 if x in 'bcd' else\
            0 #default

court et facile à lire, a une valeur par défaut et prend en charge les expressions dans les deux conditions et les valeurs de retour.

Cependant, il est moins efficace que la solution avec un dictionnaire. Par exemple, Python doit parcourir toutes les conditions avant de retourner la valeur par défaut.

5
répondu emu 2012-11-05 20:05:12

je pense que le meilleur moyen est de utilisez les idiomes du langage python pour garder votre code testable . Comme indiqué dans les réponses précédentes, j'utilise des dictionnaires pour tirer profit des structures python et du langage et garder le code" case " isolé dans différentes méthodes. Ci-dessous il y a une classe, mais vous pouvez utiliser directement un module, des globals et des fonctions. La classe dispose de méthodes qui peut être testé avec l'isolation . Dependending à votre besoins, vous pouvez jouer avec des méthodes statiques et des attributs aussi.

class ChoiceManager:

    def __init__(self):
        self.__choice_table = \
        {
            "CHOICE1" : self.my_func1,
            "CHOICE2" : self.my_func2,
        }

    def my_func1(self, data):
        pass

    def my_func2(self, data):
        pass

    def process(self, case, data):
        return self.__choice_table[case](data)

ChoiceManager().process("CHOICE1", my_data)

il est possible de profiter de cette méthode en utilisant aussi les classes comme touches de"___table de choix". De cette façon, vous pouvez éviter est l'abus de substances et garder tout propre et testable.

supposons que vous ayez à traiter un grand nombre de messages ou de paquets à partir du réseau ou de votre MQ. Chaque paquet a sa propre structure et son code de gestion (de façon générale). Avec le code ci-dessus il est possible de faire quelque chose comme ceci:

class PacketManager:

    def __init__(self):
        self.__choice_table = \
        {
            ControlMessage : self.my_func1,
            DiagnosticMessage : self.my_func2,
        }

    def my_func1(self, data):
        # process the control message here
        pass

    def my_func2(self, data):
        # process the diagnostic message here
        pass

    def process(self, pkt):
        return self.__choice_table[pkt.__class__](pkt)

pkt = GetMyPacketFromNet()
PacketManager().process(pkt)


# isolated test or isolated usage example
def test_control_packet():
    p = ControlMessage()
    PacketManager().my_func1(p)

So la complexité n'est pas étalée dans le flux de code mais elle est rendue dans la structure de code .

4
répondu J_Zar 2016-04-20 14:54:43

j'ai fait cette petite et propre solution

result = {
    'case1':     foo1, 
    'case2':     foo2,
    'case3':     foo3,
    'default':   default,
}.get(option)()

où foo1 (), foo2 (), foo3 () et default () sont des fonctions

4
répondu Alejandro Quintanar 2018-04-17 05:10:40

Définition:

def switch1(value, options):
  if value in options:
    options[value]()

vous permet d'utiliser une syntaxe assez simple, avec les cas regroupés dans une carte:

def sample1(x):
  local = 'betty'
  switch1(x, {
    'a': lambda: print("hello"),
    'b': lambda: (
      print("goodbye," + local),
      print("!")),
    })

j'ai continué à essayer de redéfinir l'interrupteur de manière à permettez-moi de se débarrasser de la "lambda:" mais abandonné. Modifier la définition:

def switch(value, *maps):
  options = {}
  for m in maps:
    options.update(m)
  if value in options:
    options[value]()
  elif None in options:
    options[None]()

M'a permis d'associer plusieurs cas au même code, et de fournir une option par défaut:

def sample(x):
  switch(x, {
    _: lambda: print("other") 
    for _ in 'cdef'
    }, {
    'a': lambda: print("hello"),
    'b': lambda: (
      print("goodbye,"),
      print("!")),
    None: lambda: print("I dunno")
    })

chacun cas répliqué doit être dans son propre dictionnaire; switch () consolide les dictionnaires avant de chercher la valeur. Il est encore plus moche que je ne le voudrais, mais il a l'efficacité de base d'utiliser une recherche hachée sur l'expression, plutôt qu'une boucle à travers toutes les touches.

3
répondu William H. Hooper 2013-07-25 18:23:33

j'étais assez confus après avoir lu la réponse, mais cela a éclairci tout:

def numbers_to_strings(argument):
    switcher = {
        0: "zero",
        1: "one",
        2: "two",
    }
    return switcher.get(argument, "nothing")

ce code est analogue à:

function(argument){
    switch(argument) {
        case 0:
            return "zero";
        case 1:
            return "one";
        case 2:
            return "two";
        default:
            return "nothing";
    }
}

cochez la case Source pour en savoir plus sur la mise en correspondance des dictionnaires avec les fonctions.

3
répondu Yster 2017-06-19 11:49:28

une solution que j'ai tendance à utiliser qui fait également usage de dictionnaires est:

def decision_time( key, *args, **kwargs):
    def action1()
        """This function is a closure - and has access to all the arguments"""
        pass
    def action2()
        """This function is a closure - and has access to all the arguments"""
        pass
    def action3()
        """This function is a closure - and has access to all the arguments"""
        pass

   return {1:action1, 2:action2, 3:action3}.get(key,default)()

cela a l'avantage qu'il n'essaie pas d'évaluer les fonctions à chaque fois, et vous avez juste à vous assurer que la fonction externe obtient toutes les informations dont les fonctions internes ont besoin.

3
répondu Tony Suffolk 66 2018-06-06 16:45:58

Inspiré par cette réponse impressionnante . Ne nécessite pas de code externe. Pas testé. De l'automne à travers ne fonctionne pas correctement.

for case in [expression]:
    if case == 1:
        do_stuff()
        # Fall through

    # Doesn't fall through INTO the later cases
    if case in range(2, 5):
        do_other_stuff()
        break

    do_default()
3
répondu Solomon Ucko 2018-09-26 21:44:57

si vous ne vous inquiétez pas perte de syntaxe surligner à l'intérieur des suites de cas, vous pouvez faire ce qui suit:

exec {
    1: """
print ('one')
""", 
    2: """
print ('two')
""", 
    3: """
print ('three')
""",
}.get(value, """
print ('None')
""")

value est la valeur. En C, ce serait:

switch (value) {
    case 1:
        printf("one");
        break;
    case 2:
        printf("two");
        break;
    case 3:
        printf("three");
        break;
    default:
        printf("None");
        break;
}

nous pouvons aussi créer une fonction helper pour faire ceci:

def switch(value, cases, default):
    exec cases.get(value, default)

Si nous pouvons l'utiliser comme ça pour l'exemple avec un, deux et trois:

switch(value, {
    1: """
print ('one')
    """, 
    2: """
print ('two')
    """, 
    3: """
print ('three')
    """,
}, """
print ('None')
""")
2
répondu DCPY 2016-05-25 22:56:30

Élargir Greg Hewgill la réponse de - Nous pouvons encapsuler le dictionnaire de la solution à l'aide d'un décorateur:

def case(callable):
    """switch-case decorator"""
    class case_class(object):
        def __init__(self, *args, **kwargs):
            self.args = args
            self.kwargs = kwargs

        def do_call(self):
            return callable(*self.args, **self.kwargs)

return case_class

def switch(key, cases, default=None):
    """switch-statement"""
    ret = None
    try:
        ret = case[key].do_call()
    except KeyError:
        if default:
            ret = default.do_call()
    finally:
        return ret

peut alors être utilisé avec le @case - décorateur

@case
def case_1(arg1):
    print 'case_1: ', arg1

@case
def case_2(arg1, arg2):
    print 'case_2'
    return arg1, arg2

@case
def default_case(arg1, arg2, arg3):
    print 'default_case: ', arg1, arg2, arg3

ret = switch(somearg, {
    1: case_1('somestring'),
    2: case_2(13, 42)
}, default_case(123, 'astring', 3.14))

print ret

la bonne nouvelle est que cela a déjà été fait dans neopyswitch - module. Il suffit d'installer en utilisant pip:

pip install NeoPySwitch
2
répondu Tom 2017-05-23 12:26:42