Frage Ersatz für switch-Anweisung in Python?


Ich möchte eine Funktion in Python schreiben, die verschiedene feste Werte basierend auf dem Wert eines Eingabeindex zurückgibt.

In anderen Sprachen würde ich ein verwenden switch oder case Anweisung, aber Python scheint keine zu haben switch Erklärung. Was sind die empfohlenen Python-Lösungen in diesem Szenario?


1440
2017-09-13 00:36


Ursprung


Antworten:


Du könntest ein Wörterbuch benutzen:

def f(x):
    return {
        'a': 1,
        'b': 2,
    }[x]

1125
2017-09-13 00:38



Wenn Sie Standardwerte verwenden möchten, können Sie das Wörterbuch verwenden get(key[, default]) Methode:

def f(x):
    return {
        'a': 1,
        'b': 2
    }.get(x, 9)    # 9 is default if x not found

1108
2017-09-19 15:45



Ich habe es immer schon so gemacht

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

Von hier


293
2017-09-13 00:41



Zusätzlich zu den Dictionary-Methoden (die ich wirklich mag, BTW), können Sie auch if-elif-else verwenden, um die switch / case / default-Funktionalitä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 mit switch / case - Sie können nicht so leicht durchfallen wie die Pause; Aussage, aber Sie können einen komplizierteren Test haben. Seine Formatierung ist schöner als eine Reihe von verschachtelten ifs, obwohl es funktional näher ist.


248
2017-09-13 01:10



Mein Lieblings-Python-Rezept für Switch / Case ist:

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 mithilfe von Tupeln zuweisen:

choices = {'a': (1, 2, 3), 'b': (4, 5, 6)}
(result1, result2, result3) = choices.get(key, ('default1', 'default2', 'default3'))

122
2018-06-17 02:25



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))

Verwendung:

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.

85
2017-07-07 06:09



Es gibt ein Muster, das ich aus Twisted Python-Code gelernt habe.

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 jederzeit verwenden, wenn Sie ein Token versenden und einen erweiterten Code ausführen müssen. In einer Staatsmaschine hättest du state_ Methoden und Versand an self.state. Dieser Schalter kann sauber erweitert werden, indem er von der Basisklasse erbt und Ihre eigene definiert do_ Methoden. Oftmals wirst du es gar nicht haben do_ Methoden in der Basisklasse.

Edit: Wie genau wird das verwendet?

Im Falle von SMTP erhalten Sie HELO vom Draht. Der relevante Code (von twisted/mail/smtp.py, für unseren Fall modifiziert) sieht so 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

Du wirst erhalten ' HELO foo.bar.com ' (Oder Sie könnten bekommen 'QUIT' oder 'RCPT TO: foo'). Dies wird in Tokenisiert parts wie ['HELO', 'foo.bar.com']. Der Name der tatsächlichen Methodennachschlage stammt aus parts[0].

(Die ursprüngliche Methode wird auch genannt state_COMMAND, weil es das gleiche Muster verwendet, um eine Zustandsmaschine zu implementieren, d.h. getattr(self, 'state_' + self.mode))


41
2017-09-13 01:26