Mein Favorit ist ein wirklich schönes Rezept . Es ist das, was den tatsächlichen switch case-Anweisungen am nächsten kommt, vor allem in Features.
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!"
In einigen Kommentaren wurde darauf hingewiesen, dass eine Kontextmanagerlösung mit with foo as case
statt for case in foo
könnte sauberer sein, und für große Schalteranweisungen könnte das lineare statt quadratische Verhalten ein netter Zug sein. Ein Teil des Wertes dieser Antwort mit einer for-Schleife ist die Möglichkeit, Unterbrechungen und Fallthroughs zu haben, und wenn wir bereit sind, mit der Wahl unserer Schlüsselwörter ein wenig zu spielen, können wir das auch in einem Kontextmanager erreichen:
class Switch:
def __init__(self, value):
self.value = value
self._entered = False
self._broken = False
self._prev = None
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
return False # Allows a traceback to occur
def __call__(self, *values):
if self._broken:
return False
if not self._entered:
if values and self.value not in values:
return False
self._entered, self._prev = True, values
return True
if self._prev is None:
self._prev = values
return True
if self._prev != values:
self._broken = True
return False
if self._prev == values:
self._prev = None
return False
@property
def default(self):
return self()
Hier ist ein Beispiel:
# Prints 'bar' then 'baz'.
with Switch(2) as case:
while case(0):
print('foo')
while case(1, 2, 3):
print('bar')
while case(4, 5):
print('baz')
break
while case.default:
print('default')
break
77 Stimmen
PEP zum Thema, verfasst von Guido selbst: PEP 3103
28 Stimmen
@chb In diesem PEP erwähnt Guido nicht, dass if/elif-Ketten auch eine klassische Fehlerquelle sind. Es ist ein sehr anfälliges Konstrukt.
15 Stimmen
Was bei allen Lösungen fehlt, ist die Erkennung von doppelte Fallwerte . Als Fail-Fast-Prinzip kann dies ein größerer Verlust sein als die Leistung oder die Fallthrough-Funktion.
6 Stimmen
switch
ist tatsächlich "vielseitiger" als etwas, das verschiedene feste Werte auf der Grundlage des Wertes eines Eingabeindexes zurückgibt. Sie ermöglicht die Ausführung verschiedener Codestücke. Sie muss nicht einmal einen Wert zurückgeben. Ich frage mich, ob einige der Antworten hier ein guter Ersatz für eine allgemeineswitch
Anweisung oder nur für den Fall, dass Werte zurückgegeben werden, ohne dass die Möglichkeit besteht, allgemeinen Code auszuführen.1 Stimmen
@sancho.s - vereinbart. Wenn Sie nicht zurückkehren oder sich von Ihrem
switch
case
Anweisung dann todo In den übrigen Fällen wird der Code ausgeführt. Das ist eindeutig nicht dasselbe wie eine Sammlung von if/elseifs3 Stimmen
Auf die gleiche Weise erfüllen Syntaxen wie Rubys case...when... (oder Scalas match, Haskells case, Perls given/when) einen allgemeinen Anwendungsfall und bieten eine mächtige Abstraktion. if...elif... ist ein schlechter Ersatz.
1 Stimmen
Pythons Aphorismus, dass "explizit besser ist als implizit" ist das, was Fall-Through in Python nicht zum Standard macht. Ich weiß nicht, ob ich traurig oder glücklich sein soll :|