Ersatz für switch-Anweisung in Python?
-
09-06-2019 - |
Frage
Ich möchte eine Funktion in Python schreiben, die verschiedene feste Werte zurück auf den Wert eines Eingangsindex.
In anderen Sprachen würde ich eine switch
oder case
Anweisung verwenden, aber Python scheint keine switch
Aussage zu haben. Was sind die empfohlenen Python-Lösungen in diesem Szenario?
Lösung
Sie können ein Wörterbuch verwenden:
def f(x):
return {
'a': 1,
'b': 2,
}[x]
Andere Tipps
Wenn Sie defaults möchten Sie das Wörterbuch verwenden könnte get(key[, default])
Methode:
def f(x):
return {
'a': 1,
'b': 2
}.get(x, 9) # 9 is default if x not found
Ich habe immer gemocht es auf diese Weise tun
result = {
'a': lambda x: x * 5,
'b': lambda x: x + 7,
'c': lambda x: x - 2
}[value](x)
Neben den Wörterbuch Methoden (die Ich mag, BTW), können Sie auch verwenden, wenn-elif-else den Schalter / case / Standardfunktionalität zu erhalten:
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
Das ist natürlich nicht identisch wechseln / Fall - Sie sind nicht so leicht durchsturz als Weglassen der Pause haben kann; Aussage, aber Sie können einen komplizierteren Test haben. Seine Formatierung ist schöner als eine Reihe von verschachtelten ifs, obwohl funktionell das ist, was es ist näher an.
Mein Lieblings-Python Rezept für Schalter / Fall ist:
choices = {'a': 1, 'b': 2}
result = choices.get(key, 'default')
Kurz und knapp für einfache Szenarien.
Vergleichen Sie bis zu 11+ Zeilen C-Code:
// C Language version of a simple 'switch/case'.
switch( key )
{
case 'a' :
result = 1;
break;
case 'b' :
result = 2;
break;
default :
result = -1;
}
Sie können sogar mehr Variablen zuweisen, indem Tupel mit:
choices = {'a': (1, 2, 3), 'b': (4, 5, 6)}
(result1, result2, result3) = choices.get(key, ('default1', 'default2', 'default3'))
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))
Verbrauch:
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.
Es ist ein Muster, das ich von Twisted-Python-Code gelernt.
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'
Sie können es verwenden, jedes Mal, wenn Sie auf einem Token versenden müssen und erweiterte Stück Code ausführen. In einer Zustandsmaschine würden Sie state_
Methoden und versenden am self.state
haben. Dieser Schalter kann sauber durch Erben von Basisklasse erweitert werden und Ihre eigenen do_
Methoden definieren. Oft werden Sie nicht einmal do_
Methoden in der Basisklasse haben.
Edit: Wie genau ist, dass verwendet
Bei SMTP werden Sie HELO
aus dem Draht erhalten. Der entsprechende Code (von twisted/mail/smtp.py
, für unseren Fall geändert) sieht wie folgt aus
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
Sie empfangen ' HELO foo.bar.com '
(oder Sie könnten 'QUIT'
oder 'RCPT TO: foo'
bekommen). Dies wird in parts
als ['HELO', 'foo.bar.com']
Token versehen. Der tatsächliche Methode Lookup-Name wird von parts[0]
genommen.
(Die ursprüngliche Methode auch state_COMMAND
genannt wird, weil es das gleiche Muster verwendet eine Zustandsmaschine zu implementieren, das heißt getattr(self, 'state_' + self.mode)
)
Mein Favorit ist ein wirklich schönes Rezept rel="nofollow. Sie mögen es wirklich. Es ist die nächstgelegene ich tatsächliche Schaltergehäuse Aussagen gesehen habe, vor allem in Funktionen.
class switch(object):
def __init__(self, value):
self.value = value
self.fall = False
def __iter__(self):
"""Return the match method once, then stop"""
yield self.match
raise StopIteration
def match(self, *args):
"""Indicate whether or not to enter a case suite"""
if self.fall or not args:
return True
elif self.value in args: # changed for v1.5, see below
self.fall = True
return True
else:
return False
Hier ist ein Beispiel:
# 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!"
class Switch:
def __init__(self, value):
self.value = value
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
return False # Allows a traceback to occur
def __call__(self, *values):
return self.value in values
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
Angenommen, Sie wollen nicht nur einen Wert zurückgeben, will aber Methoden verwenden, die auf einem Objekt etwas ändern. der Ansatz hier angegeben Mit wäre:
result = {
'a': obj.increment(x),
'b': obj.decrement(x)
}.get(value, obj.default(x))
Was hier passiert, ist, dass Python alle Methoden im Wörterbuch auswertet. Also selbst wenn Ihr Wert 'a' ist, wird erhalten das Objekt erhöht und erniedrigt durch x.
Lösung:
func, args = {
'a' : (obj.increment, (x,)),
'b' : (obj.decrement, (x,)),
}.get(value, (obj.default, (x,)))
result = func(*args)
So haben Sie eine Liste bekommen eine Funktion und deren Argumente enthält. Auf diese Weise wird nur der Funktionszeiger und die Argumentliste zurückerhalten, nicht ausgewertet. ‚Ergebnis‘ wertet dann den zurückgegebene Funktionsaufruf.
Ich werde einfach hier meine zwei Cent fallen zu lassen. Der Grund, es ist kein Fall / switch-Anweisung in Python ist, weil Python das Prinzip der ‚Es gibt nur einen richtigen Weg, etwas zu tun‘ folgt. So offensichtlich konnte man mit verschiedenen Möglichkeiten der Neuen switch / case Funktionalität kommen, aber der Pythonic Weg, dies zu erreichen, ist die if / elif Konstrukt. dh
if something:
return "first thing"
elif somethingelse:
return "second thing"
elif yetanotherthing:
return "third thing"
else:
return "default thing"
Ich fühlte mich nur 8 PEP ein Nicken verdient hier. Eines der schönen Dinge über Python ist seine Einfachheit und Eleganz. Das ist weitgehend von den Prinzipien abgeleitet gelegt unseren in PEP 8, darunter „Es gibt nur einen richtigen Weg, etwas zu tun“
auf der „dict als Schalter“ Idee zu erweitern. wenn Sie einen Standardwert für Ihren Schalter verwenden:
def f(x):
try:
return {
'a': 1,
'b': 2,
}[x]
except KeyError:
return 'default'
Wenn Sie einen komplizierten Fall Block können Sie prüfen eine Funktion Wörterbuch Lookup-Tabelle mit ...
Wenn Sie dies nicht getan haben, bevor es eine gute Idee, in Ihren Debugger Schritt und genau sehen, wie das Wörterbuch jede Funktion nachschlägt.
Hinweis: Do nicht Verwendung „()“ im Inneren des Gehäuses / Wörterbuchsuche oder es wird jede Ihrer Funktionen aufrufen, wie das Wörterbuch / case-Block erstellt wird. Erinnern Sie sich daran, weil Sie nur jede Funktion aufgerufen werden soll, wenn ein Hash-Stil-Lookup verwendet wird.
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()
Wenn Sie extra Anweisung sind, als „Schalter“, baute ich ein Python-Modul, das Python erweitert. Es heißt ESPY als "Enhanced Struktur für Python" und es ist für beide Python 2.x und Python 3.x.
Zum Beispiel, in diesem Fall eine switch-Anweisung durch den folgenden Code ausgeführt werden:
macro switch(arg1):
while True:
cont=False
val=%arg1%
socket case(arg2):
if val==%arg2% or cont:
cont=True
socket
socket else:
socket
break
, die wie folgt verwendet werden:
a=3
switch(a):
case(0):
print("Zero")
case(1):
print("Smaller than 2"):
break
else:
print ("greater than 1")
so espy übersetzt es in Python als:
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
Ich habe nicht die einfache Antwort finde ich wurde auf Google-Suche nach überall suchen. Aber ich dachte, es trotzdem aus. Es ist wirklich ganz einfach. Beschlossen, es zu senden, und vielleicht ein paar wenigen Kratzer auf einem fremden Kopf zu verhindern. Der Schlüssel ist, einfach „in“ und Tupel. Hier ist das switch-Anweisung Verhalten mit Durchfall, einschließlich RANDOM Durchfall.
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)
Provides:
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.
Ich fand, dass eine gemeinsame Schalterstruktur:
switch ...parameter...
case p1: v1; break;
case p2: v2; break;
default: v3;
kann in Python wie folgt ausgedrückt werden:
(lambda x: v1 if p1(x) else v2 if p2(x) else v3)
oder in einer klareren Weise formatiert:
(lambda x:
v1 if p1(x) else
v2 if p2(x) else
v3)
Stattdessen eine Erklärung des Seins, die Python-Version ist ein Ausdruck, der auf einen Wert auswertet.
Die Lösungen, die ich verwenden:
Eine Kombination von zwei der Lösungen hier gepostet, die relativ leicht zu lesen und unterstützt Standardwerte.
result = {
'a': lambda x: x * 5,
'b': lambda x: x + 7,
'c': lambda x: x - 2
}.get(whatToUse, lambda x: x - 22)(value)
Dabei steht
.get('c', lambda x: x - 22)(23)
sucht "lambda x: x - 2"
im dict und verwendet sie mit x=23
.get('xxx', lambda x: x - 22)(44)
ist es nicht in der dict finden und verwendet den Standard "lambda x: x - 22"
mit x=44
.
# 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
Die meisten Antworten hier sind ziemlich alt, und vor allem der akzeptierten, so scheint es wert aktualisiert werden.
Zuerst wird die offizielle PEP 275 , was geschrieben wurde, eine bekommen offiziell einmal und für alle Mögliche Entscheidung über die C-style switch-Anweisungen hinzufügen. Aber das PEP wurde tatsächlich zu Python latenten 3, und es wurde nur offiziell als separater Vorschlag abgelehnt, PEP 3103 . Die Antwort war natürlich keine, aber die beiden Pep Links zu weiteren Informationen haben, wenn Sie in den Gründen oder die Geschichte interessiert sind.
Eine Sache, die mehrere Male kam (und kann in PEP 275, auch gesehen werden, obwohl es wurde als eine tatsächliche Empfehlung ausgeschnitten) ist, dass, wenn Sie wirklich gestört von 8 Zeilen Code mit 4 Fälle zu behandeln, vs . die 6 Zeilen, die Sie in C oder Bash haben würde, können Sie dies immer schreiben kann:
if x == 1: print('first')
elif x == 2: print('second')
elif x == 3: print('third')
else: print('did not place')
Dies ist nicht gerade ermutigt durch PEP 8, aber es ist lesbar und nicht zu unidiomatic.
über die mehr als ein Jahrzehnt seit PEP 3103 abgelehnt wurde, die Frage der C-Stil Fall Aussagen oder auch die etwas leistungsstärkere Version in Go ist tot gegolten; wenn jemand es nach oben auf Python-Ideen oder -dev bringt, sind sie auf die alte Entscheidung bezeichnet.
Es stellt sie allerdings die Idee des vollständigen ML-Stil Pattern Matching all paar Jahre, zumal Sprachen wie Swift und Rust haben es angenommen. Das Problem ist, dass es schwer viel Nutzen aus Musterabgleich ohne algebraische Datentypen zu erhalten. Während Guido auf die Idee sympathisch gewesen, niemand mit einem Vorschlag kommen, die sehr gut in Python paßt. (Lesen Sie mein 2014 strawman für ein Beispiel) Summe Typen in 3.7 und einige sporadische Vorschläge für eine leistungsfähigere dataclass
mit enum
ändern zu handhaben, oder mit verschiedenen Vorschläge für verschiedene Arten von Anweisungs lokalen Bindungen (wie PEP 3150 , oder die Reihe von Vorschlägen zur Zeit auf -Ideen diskutiert). Aber bisher hat es nicht.
Es gibt vereinzelt auch Vorschläge für Perl 6-Abgleich verwendet, die im Grunde ein Mischmasch von allem von elif
an einzelsträngige Versandart-Umschaltung auf regulären Ausdruck ist.
def f(x):
dictionary = {'a':1, 'b':2, 'c':3}
return dictionary.get(x,'Not Found')
##Returns the value for the letter x;returns 'Not Found' if x isn't a key in the dictionary
Ich mochte Mark Bies Antwort
Da die x
Variable zweimal verwendet wird, muss geändert ich die Lambda-Funktionen auf parameterlos.
Ich habe mit results[value](value)
laufen
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: Ich habe bemerkt, dass ich None
Typ mit mit Wörterbücher verwenden können. So würde die switch ; case else
emulieren
Lösung ausführen Funktionen:
result = {
'case1': foo1,
'case2': foo2,
'case3': foo3,
'default': default,
}.get(option)()
Dabei gilt foo1 (), foo2 (), foo3 () und Standard () Funktionen
def f(x):
return 1 if x == 'a' else\
2 if x in 'bcd' else\
0 #default
Kurz und leicht zu lesen, hat einen Standardwert und unterstützt Ausdrücke in beiden Bedingungen und Werte zurück.
Es ist jedoch weniger effizient als die Lösung mit einem Wörterbuch. Zum Beispiel hat Python durch alle Bedingungen zu überprüfen, bevor Sie den Standardwert zurück.
Ich denke, der beste Weg, um ist verwenden die Sprache Python Idiome Code testbar zu halten . Wie bereits in früheren Antworten zeigten, verwende ich Wörterbücher nutzen Python Strukturen und Sprache und halten den „Fall“ Code in verschiedenen Methoden isoliert. Unten gibt es eine Klasse, aber Sie können direkt ein Modul, Globals und Funktionen verwenden. Die Klasse hat Methoden, die kann mit Isolation getestet werden . Dependending auf Ihre Bedürfnisse, können Sie mit statischen Methoden spielen und auch Attribute.
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)
Es ist möglich, Vorteil dieser Methode nimmt auch mit Klassen als Schlüssel von „__choice_table“. Auf diese Weise können Sie vermeiden, isinstance Missbrauch und halten alles sauber und prüfbar.
Angenommen, Sie eine Menge von Nachrichten oder Paketen aus dem Netz oder MQ zu verarbeiten haben. Jedes Paket hat seine eigene Struktur und seinen Management-Code (in allgemeiner Weise). Mit dem obigen Code ist es möglich, so etwas zu tun:
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 Komplexität ist nicht im Code Strömung verteilt, aber es wird in Codestruktur gemacht .
Die Erweiterung auf Greg Hewgill Antwort - Wir können die Wörterbuch-Lösung mit einem Dekorateur kapseln:
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
Dieses kann dann mit dem @case
-Dekorateur verwendet werden
@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
Die gute Nachricht ist, dass dies bereits in NeoPySwitch - Modul. Einfach installieren pip mit:
pip install NeoPySwitch
Eine Lösung, die ich zu verwenden, neigen dazu, die auch die Verwendung von Wörterbüchern macht, ist:
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)()
Dies hat den Vorteil, dass es nicht die Funktionen nicht versuchen, jedes Mal zu bewerten, und Sie müssen nur sicherstellen, dass die äußere Funktion alle Informationen bekommt, dass die inneren Funktionen benötigen.
Sie können versandt dict verwenden:
#!/usr/bin/env python
def case1():
print("This is case 1")
def case2():
print("This is case 2")
def case3():
print("This is case 3")
token_dict = {
"case1" : case1,
"case2" : case2,
"case3" : case3,
}
def main():
cases = ("case1", "case3", "case2", "case1")
for case in cases:
token_dict[case]()
if __name__ == '__main__':
main()
Ausgabe:
This is case 1
This is case 3
This is case 2
This is case 1
Einfache, nicht getestet; jede Bedingung unabhängig ausgewertet: Es gibt keine Durchfall, aber alle Fälle ausgewertet werden (obwohl der Ausdruck nur ein- einmal ausgewertet wird), es sei denn, es gibt eine break-Anweisung. Zum Beispiel:
for case in [expression]:
if case == 1:
print(end='Was 1. ')
if case == 2:
print(end='Was 2. ')
break
if case in (1, 2):
print(end='Was 1 or 2. ')
print(end='Was something. ')
druckt Was 1. Was 1 or 2. Was something.
(Dammit! Warum kann ich nicht haben nachfolgende Leerzeichen in Inline-Code-Blöcke?) , wenn expression
auswertet, 1
Was 2.
wenn expression
2
auswertet, oder Was something.
wenn expression
auf etwas anderes auswertet .
Definition:
def switch1(value, options):
if value in options:
options[value]()
können Sie eine ziemlich einfache Syntax verwenden, wobei die Fälle in einer Karte gebündelt:
def sample1(x):
local = 'betty'
switch1(x, {
'a': lambda: print("hello"),
'b': lambda: (
print("goodbye," + local),
print("!")),
})
ich immer wieder versucht, Schalter in einer Weise neu zu definieren, die mich loszuwerden, die erhalten lassen würde „Lambda“, aber aufgab. Zwicken die Definition:
def switch(value, *maps):
options = {}
for m in maps:
options.update(m)
if value in options:
options[value]()
elif None in options:
options[None]()
erlaubt mir mehrere Fälle auf den gleichen Code abzubilden, und eine Standardoption zu liefern:
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")
})
Jeder replizierte Fall hat in einem eigenen Wörterbuch sein; Schalter () konsolidiert die Wörterbücher, bevor Sie den Wert nach oben. Es ist immer noch hässlicher als ich mag, aber es hat die grundlegende Effizienz einen Hash-Lookup auf der Expression, anstatt eine Schleife durch alle Tasten.
Wenn Sie keine Sorge Syntax Highlight im Inneren der Fall Suiten zu verlieren, können Sie wie folgt vor:
exec {
1: """
print ('one')
""",
2: """
print ('two')
""",
3: """
print ('three')
""",
}.get(value, """
print ('None')
""")
Wo value
ist der Wert. In C würde dies sein:
switch (value) {
case 1:
printf("one");
break;
case 2:
printf("two");
break;
case 3:
printf("three");
break;
default:
printf("None");
break;
}
Wir können auch eine Hilfsfunktion, dies zu tun erstellen:
def switch(value, cases, default):
exec cases.get(value, default)
So wir es, wie dies für das Beispiel mit einem verwenden können, zwei und drei:
switch(value, {
1: """
print ('one')
""",
2: """
print ('two')
""",
3: """
print ('three')
""",
}, """
print ('None')
""")