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?

War es hilfreich?

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)

Von hier

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')
""")
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top