Ich möchte eine Funktion in Python schreiben, die basierend auf dem Wert eines Eingabeindex verschiedene feste Werte zurückgibt.
In anderen Sprachen würde ich a verwenden switch oder case -Anweisung, aber Python scheint keine zu haben switch Aussage. Was sind die empfohlenen Python-Lösungen in diesem Szenario?
Zugehöriger PEP, verfasst von Guido selbst: PEP 3103
– chb
16. Juni 2012 um 17:22 Uhr
@chb In diesem PEP erwähnt Guido nicht, dass if/elif-Ketten auch eine klassische Fehlerquelle sind. Es ist ein sehr fragiles Konstrukt.
– es ist Bruce
9. Januar 2014 um 13:46 Uhr
Bei allen Lösungen fehlt hier die Erkennung von Doppelte Fallwerte. Als Fail-Fast-Prinzip kann dies ein wichtigerer Verlust sein als die Leistung oder die Fallthrough-Funktion.
– Bob Stein
17. Oktober 2014 um 19:04 Uhr
switch ist tatsächlich “vielseitiger” als etwas, das basierend auf dem Wert eines Eingabeindex unterschiedliche feste Werte zurückgibt. Es ermöglicht die Ausführung verschiedener Codeteile. Es muss eigentlich nicht einmal ein Wert zurückgegeben werden. Ich frage mich, ob einige der Antworten hier ein guter Ersatz für einen General sind switch -Anweisung oder nur für den Fall, dass Werte zurückgegeben werden, ohne dass allgemeine Codeteile ausgeführt werden können.
– sancho.s ReinstateMonicaCellio
14. Mai 2017 um 21:29 Uhr
Auf die gleiche Weise treffen Syntaxen wie Rubys Fall … wenn … (oder Scalas Übereinstimmung, Haskells Fall, Perls gegebenes/wann) auf einen gemeinsamen Anwendungsfall und bieten eine starke Abstraktion. if…elif… ist ein schlechter Ersatz.
– es ist Bruce
1. Oktober 2017 um 7:14 Uhr
Nick
Wenn Sie Standardeinstellungen möchten, können Sie das Wörterbuch verwenden get(key[, default]) Funktion:
def f(x):
return {
'a': 1,
'b': 2
}.get(x, 9) # 9 will be returned default if x is not found
Was ist, wenn ‘a’ und ‘b’ mit 1 übereinstimmen und ‘c’ und ‘d’ mit 2 übereinstimmen?
– John Mei
9. April 2010 um 7:57 Uhr
@JM: Nun, offensichtlich unterstützen Wörterbuchsuchen keine Fall-Throughs. Sie könnten eine doppelte Wörterbuchsuche durchführen. Dh ‘a’ & ‘b’ zeigen auf Antwort1 und ‘c’ und ‘d’ zeigen auf Antwort2, die in einem zweiten Wörterbuch enthalten sind.
– Nik
9. April 2010 um 9:54 Uhr
es ist besser, einen Standardwert zu übergeben
– HaTiMSum
13. Oktober 2016 um 11:01 Uhr
Es gibt ein Problem mit diesem Ansatz, erstens jedes Mal, wenn Sie f aufrufen, um das Diktat erneut zu erstellen, zweitens, wenn Sie einen komplexeren Wert haben, können Sie Ausnahmen erhalten, z. wenn x ein Tupel ist und wir so etwas tun wollen x = (‘a’) def f(x): return { ‘a’: x[0]’b’: x[1] }.get(x[0]9) Dadurch wird IndexError ausgelöst
– Idan Haim Shalom
30. August 2017 um 8:01 Uhr
@Idan: Die Frage war, den Schalter zu replizieren. Ich bin mir sicher, dass ich diesen Code auch knacken könnte, wenn ich versuchen würde, ungerade Werte einzugeben. Ja, es wird neu erstellt, aber es ist einfach zu beheben.
– Nick
19. September 2017 um 21:59 Uhr
Er fragt nach festen Werten. Warum eine Funktion generieren, um etwas zu berechnen, wenn es sich um eine Suche handelt? Interessante Lösung für andere Probleme.
– Nick
21. Januar 2010 um 17:06 Uhr
Es ist vielleicht keine gute Idee, in diesem Fall Lambda zu verwenden, da Lambda tatsächlich jedes Mal aufgerufen wird, wenn das Wörterbuch erstellt wird.
– Ascher
22. April 2012 um 21:48 Uhr
Leider ist dies das nächste, was die Leute bekommen werden. Methoden, die verwenden .get() (wie die aktuell höchsten Antworten) vor dem Versand alle Möglichkeiten eifrig evaluieren müssen und daher nicht nur (nicht nur sehr, sondern) extrem ineffizient sind und auch keine Nebenwirkungen haben können; Diese Antwort umgeht dieses Problem, ist aber ausführlicher. Ich würde nur if/elif/else verwenden, und selbst diese brauchen genauso lange zum Schreiben wie ‘case’.
– Ninjagecko
17. März 2014 um 13:48 Uhr
Würde dies nicht jedes Mal in allen Fällen alle Funktionen/Lambdas auswerten, auch wenn nur eines der Ergebnisse zurückgegeben wird?
– slf
6. August 2014 um 19:04 Uhr
@slf Nein, wenn der Kontrollfluss diesen Codeabschnitt erreicht, erstellt er 3 Funktionen (durch die Verwendung der 3 Lambdas) und erstellt dann ein Wörterbuch mit diesen 3 Funktionen als Werte, aber sie bleiben unaufgerufen (auswerten ist in diesem Zusammenhang zunächst etwas zweideutig). Dann wird das Wörterbuch über indiziert [value]die nur eine der 3 Funktionen zurückgibt (vorausgesetzt value ist einer der 3 Schlüssel). Die Funktion wurde zu diesem Zeitpunkt noch nicht aufgerufen. Dann (x) ruft die gerade zurückgegebene Funktion mit auf x als Argument (und das Ergebnis geht an result). Die anderen 2 Funktionen werden nicht aufgerufen.
– blubberdiblub
18. September 2015 um 6:11 Uhr
Zusätzlich zu den Wörterbuchmethoden (die ich übrigens sehr mag) können Sie auch verwenden if–elif–else um die zu erhalten switch/case/default Funktionalität:
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
Dies ist natürlich nicht identisch mit Switch/Case – Sie können nicht so leicht durchfallen wie das weglassen break Aussage, aber Sie können einen komplizierteren Test haben. Seine Formatierung ist schöner als eine Reihe von verschachtelten ifs, obwohl es funktionell näher dran ist.
Ich würde das wirklich bevorzugen, es verwendet ein Standard-Sprachkonstrukt und wirft keinen KeyError, wenn kein passender Fall gefunden wird
– martyglaubitz
18. Mai 2013 um 10:30 Uhr
Ich dachte an das Wörterbuch / get Weg, aber der Standardweg ist einfach besser lesbar.
– Martin Thoma
25. Juni 2015 um 6:33 Uhr
@someuser, aber die Tatsache, dass sie sich “überschneiden” können, ist eine Funktion. Sie stellen nur sicher, dass die Reihenfolge die Priorität ist, in der Übereinstimmungen auftreten sollten. Wie für wiederholtes x: mach einfach ein x = the.other.thing Vor. Normalerweise haben Sie ein einzelnes if, mehrere elif und ein einzelnes else, da dies einfacher zu verstehen ist.
– Matthäus Schinckel
3. März 2016 um 6:55 Uhr
Schön, das “Fall-through by not using elif ” ist allerdings etwas verwirrend. Was ist damit: vergiss “durchfallen” und akzeptiere es einfach als zwei if/elif/else‘s?
– Alois Mahdal
30. Mai 2016 um 11:40 Uhr
Erwähnenswert auch, wenn Dinge wie verwendet werden x in 'bc'Denk daran, dass "" in "bc" ist True.
– Lohmar ASCHAR
28. August 2018 um 11:46 Uhr
Python >= 3.10
Wow, Python 3.10+ hat jetzt eine match/case Syntax, die wie ist switch/case und mehr!
Das Abgleichen von Werten ähnelt einem einfachen switch/case in einer anderen Sprache:
match something:
case 1 | 2 | 3:
# Match 1-3.
case _:
# Anything else.
#
# Match will throw an error if this is omitted
# and it doesn't match any of the other patterns.
2 – Übereinstimmungsstrukturmuster:
match something:
case str() | bytes():
# Match a string like object.
case [str(), int()]:
# Match a `str` and an `int` sequence
# (`list` or a `tuple` but not a `set` or an iterator).
case [_, _]:
# Match a sequence of 2 variables.
# To prevent a common mistake, sequence patterns don’t match strings.
case {"bandwidth": 100, "latency": 300}:
# Match this dict. Extra keys are ignored.
3 – Variablen erfassen
Analysieren Sie ein Objekt; als Variablen speichern:
match something:
case [name, count]
# Match a sequence of any two objects and parse them into the two variables.
case [x, y, *rest]:
# Match a sequence of two or more objects,
# binding object #3 and on into the rest variable.
case bytes() | str() as text:
# Match any string like object and save it to the text variable.
Erfassungsvariablen können beim Analysieren von Daten (z. B. JSON oder HTML) nützlich sein, die in einem von mehreren verschiedenen Mustern vorliegen können.
Capture-Variablen ist eine Funktion. Aber es bedeutet auch, dass Sie gepunktete Konstanten verwenden müssen (z. B.: COLOR.RED) nur. Andernfalls wird die Konstante als Capture-Variable behandelt und überschrieben.
match something:
case 0 | 1 | 2:
# Matches 0, 1 or 2 (value).
print("Small number")
case [] | [_]:
# Matches an empty or single value sequence (structure).
# Matches lists and tuples but not sets.
print("A short sequence")
case str() | bytes():
# Something of `str` or `bytes` type (data type).
print("Something string-like")
case _:
# Anything not matched by the above.
print("Something else")
Python <= 3.9
Mein Lieblings-Python-Rezept für Switch/Case war:
choices = {'a': 1, 'b': 2}
result = choices.get(key, 'default')
Kurz und einfach für einfache Szenarien.
Vergleichen Sie mit mehr als 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 mehrere Variablen zuweisen, indem Sie Tupel verwenden:
Ich würde das wirklich bevorzugen, es verwendet ein Standard-Sprachkonstrukt und wirft keinen KeyError, wenn kein passender Fall gefunden wird
– martyglaubitz
18. Mai 2013 um 10:30 Uhr
Ich dachte an das Wörterbuch / get Weg, aber der Standardweg ist einfach besser lesbar.
– Martin Thoma
25. Juni 2015 um 6:33 Uhr
@someuser, aber die Tatsache, dass sie sich “überschneiden” können, ist eine Funktion. Sie stellen nur sicher, dass die Reihenfolge die Priorität ist, in der Übereinstimmungen auftreten sollten. Wie für wiederholtes x: mach einfach ein x = the.other.thing Vor. Normalerweise haben Sie ein einzelnes if, mehrere elif und ein einzelnes else, da dies einfacher zu verstehen ist.
– Matthäus Schinckel
3. März 2016 um 6:55 Uhr
Schön, das “Fall-through by not using elif ” ist allerdings etwas verwirrend. Was ist damit: vergiss “durchfallen” und akzeptiere es einfach als zwei if/elif/else‘s?
– Alois Mahdal
30. Mai 2016 um 11:40 Uhr
Erwähnenswert auch, wenn Dinge wie verwendet werden x in 'bc'Denk daran, dass "" in "bc" ist True.
– Lohmar ASCHAR
28. August 2018 um 11:46 Uhr
KurzedMetal
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))
Verwendungszweck:
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.
Dies ist nicht gefahrlos. Wenn mehrere Schalter gleichzeitig gedrückt werden, nehmen alle Schalter den Wert des letzten Schalters an.
– Francescortiz
26. Juni 2013 um 16:35 Uhr
Während @francescortiz wahrscheinlich threadsicher bedeutet, ist es auch nicht bedrohungssicher. Es bedroht die Werte der Variablen!
– Zizouz212
16. Juni 2015 um 16:29 Uhr
Das Thread-Sicherheitsproblem könnte wahrscheinlich mit umgangen werden Thread-lokaler Speicher. Oder es könnte ganz vermieden werden, indem eine Instanz zurückgegeben und diese Instanz für die Fallvergleiche verwendet wird.
– blubberdiblub
18. September 2015 um 6:24 Uhr
@blubberdiblub Aber ist es dann nicht einfach effizienter, einen Standard zu verwenden? if Aussage?
– wizzwizz4
23. Mai 2016 um 17:32 Uhr
Dies ist auch nicht sicher, wenn es in mehreren Funktionen verwendet wird. In dem angegebenen Beispiel, wenn die case(2) Block rief eine andere Funktion auf, die switch() verwendet, und dann beim Ausführen case(2, 3, 5, 7) usw., um nach dem nächsten auszuführenden Fall zu suchen, wird der von der anderen Funktion festgelegte Schalterwert verwendet, nicht der von der aktuellen Schalteranweisung festgelegte.
– Benutzer9876
17. August 2017 um 8:58 Uhr
11590300cookie-checkErsatz für switch-Anweisung in Python?yes
Zugehöriger PEP, verfasst von Guido selbst: PEP 3103
– chb
16. Juni 2012 um 17:22 Uhr
@chb In diesem PEP erwähnt Guido nicht, dass if/elif-Ketten auch eine klassische Fehlerquelle sind. Es ist ein sehr fragiles Konstrukt.
– es ist Bruce
9. Januar 2014 um 13:46 Uhr
Bei allen Lösungen fehlt hier die Erkennung von Doppelte Fallwerte. Als Fail-Fast-Prinzip kann dies ein wichtigerer Verlust sein als die Leistung oder die Fallthrough-Funktion.
– Bob Stein
17. Oktober 2014 um 19:04 Uhr
switch
ist tatsächlich “vielseitiger” als etwas, das basierend auf dem Wert eines Eingabeindex unterschiedliche feste Werte zurückgibt. Es ermöglicht die Ausführung verschiedener Codeteile. Es muss eigentlich nicht einmal ein Wert zurückgegeben werden. Ich frage mich, ob einige der Antworten hier ein guter Ersatz für einen General sindswitch
-Anweisung oder nur für den Fall, dass Werte zurückgegeben werden, ohne dass allgemeine Codeteile ausgeführt werden können.– sancho.s ReinstateMonicaCellio
14. Mai 2017 um 21:29 Uhr
Auf die gleiche Weise treffen Syntaxen wie Rubys Fall … wenn … (oder Scalas Übereinstimmung, Haskells Fall, Perls gegebenes/wann) auf einen gemeinsamen Anwendungsfall und bieten eine starke Abstraktion. if…elif… ist ein schlechter Ersatz.
– es ist Bruce
1. Oktober 2017 um 7:14 Uhr