Zamienniki dla instrukcji switch w Pythonie?
Chcę napisać funkcję w Pythonie, która zwraca różne stałe wartości na podstawie wartości indeksu wejściowego.
W innych językach używałbym instrukcji switch
LUB case
, ale Python nie wydaje się mieć instrukcji switch
. Jakie są zalecane rozwiązania Pythona w tym scenariuszu?
30 answers
Przydałby się słownik:
def f(x):
return {
'a': 1,
'b': 2,
}[x]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-13 00:38:24
Jeśli chcesz domyślnych można użyć słownika get(key[, default])
"metoda": {]}
def f(x):
return {
'a': 1,
'b': 2
}.get(x, 9) # 9 is default if x not found
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-06 22:51:30
Zawsze lubiłem robić to w ten sposób
result = {
'a': lambda x: x * 5,
'b': lambda x: x + 7,
'c': lambda x: x - 2
}[value](x)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-16 05:06:42
Oprócz metod słownikowych (które bardzo mi się podobają, BTW), możesz również użyć if-elif-else, aby uzyskać funkcjonalność switch/case / default:
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
To oczywiście nie jest identyczne z switch/case - nie można mieć przewrócenia tak łatwo, jak pomijając przerwę; stwierdzenie, ale można mieć bardziej skomplikowany test. Jego formatowanie jest ładniejsze niż szereg zagnieżdżonych ifs, chociaż funkcjonalnie do tego jest bliższe.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-10 14:07:33
Mój ulubiony przepis Pythona na switch/case to:
choices = {'a': 1, 'b': 2}
result = choices.get(key, 'default')
Krótkie i proste dla prostych scenariuszy.
Porównaj z 11 + linijkami kodu C:
// C Language version of a simple 'switch/case'.
switch( key )
{
case 'a' :
result = 1;
break;
case 'b' :
result = 2;
break;
default :
result = -1;
}
Możesz nawet przypisać wiele zmiennych za pomocą krotek:
choices = {'a': (1, 2, 3), 'b': (4, 5, 6)}
(result1, result2, result3) = choices.get(key, ('default1', 'default2', 'default3'))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-16 21:58:26
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))
Użycie:
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
Testy:
n = 2
#Result:
#n is an even number.
#n is a prime number.
n = 11
#Result:
#Only single-digit numbers are allowed.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-31 14:24:52
Jest pewien wzorzec, którego nauczyłem się z pokręconego kodu Pythona.
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'
Możesz go użyć w każdej chwili, gdy będziesz musiał wysłać token i wykonać Rozszerzony fragment kodu. W maszynie stanowej mielibyśmy metody state_
, A wysyłanie na self.state
. Ten przełącznik może być czysto rozszerzony poprzez dziedziczenie z klasy bazowej i definiowanie własnych metod do_
. Często nie będziesz mieć nawet do_
metod w klasie bazowej.
Edit: jak dokładnie jest to używane
W przypadku SMTP otrzymasz HELO
z przewodu. Odpowiedni kod (z twisted/mail/smtp.py
, zmodyfikowany dla naszego przypadku) wygląda tak:
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
Otrzymasz ' HELO foo.bar.com '
(lub możesz otrzymać 'QUIT'
lub 'RCPT TO: foo'
). To jest tokenizowane do parts
jako ['HELO', 'foo.bar.com']
. Rzeczywista nazwa metody pochodzi z parts[0]
.
(oryginalna metoda jest również nazywana state_COMMAND
, ponieważ używa tego samego wzorca do implementacji maszyny stanowej, tj. getattr(self, 'state_' + self.mode)
)
Mój ulubiony to naprawdę fajny przepis . Spodoba ci się. Jest to najbliższy, jaki widziałem do rzeczywistych instrukcji switch case, szczególnie w funkcjach.
Oto przykład:
# 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!"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-07 06:12:47
class Switch:
def __init__(self, value): self._val = value
def __enter__(self): return self
def __exit__(self, type, value, traceback): return False # Allows traceback to occur
def __call__(self, *mconds): return self._val in mconds
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-15 20:25:07
Powiedzmy, że nie chcesz po prostu zwracać wartości, ale chcesz użyć metod, które zmieniają coś na obiekcie. Używając podejścia podanego tutaj byłoby:
result = {
'a': obj.increment(x),
'b': obj.decrement(x)
}.get(value, obj.default(x))
Dzieje się tak, że python ocenia wszystkie metody w słowniku. Więc nawet jeśli twoja wartość to 'a', obiekt zostanie zwiększony i o x.
Rozwiązanie:
func, args = {
'a' : (obj.increment, (x,)),
'b' : (obj.decrement, (x,)),
}.get(value, (obj.default, (x,)))
result = func(*args)
Więc otrzymujesz listę zawierającą funkcję i jej argumenty. W ten sposób, tylko wskaźnik funkcji i lista argumentów get returned, not evaluated. 'result' następnie ocenia zwracane wywołanie funkcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-30 08:31:55
Wrzucę tu moje 2 centy. Powodem, dla którego nie ma instrukcji case/switch w Pythonie, jest to, że Python przestrzega zasady "istnieje tylko jeden właściwy sposób, aby coś zrobić". Więc oczywiście można wymyślić różne sposoby odtworzenia funkcji switch/case, ale Pythonicznym sposobem osiągnięcia tego jest konstrukcja if / elif. ie
if something:
return "first thing"
elif somethingelse:
return "second thing"
elif yetanotherthing:
return "third thing"
else:
return "default thing"
Poczułem, że PEP 8 zasługuje na ukłon. Jedną z pięknych rzeczy w Pythonie jest jego prostota i elegancja. Że w dużej mierze opiera się na zasadach określonych w PEP 8, w tym "jest tylko jeden właściwy sposób, aby coś zrobić"Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-14 22:19:38
Rozszerzenie idei "dict as switch". jeśli chcesz użyć domyślnej wartości dla przełącznika:
def f(x):
try:
return {
'a': 1,
'b': 2,
}[x]
except KeyError:
return 'default'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-19 15:37:15
Jeśli masz skomplikowany blok przypadków, możesz rozważyć użycie tabeli wyszukiwania słownika funkcji...
Jeśli nie zrobiłeś tego wcześniej, dobrym pomysłem jest wejście do debuggera i zobacz dokładnie, jak słownik wygląda każdej funkcji.
Uwaga: czy nie używaj "() " wewnątrz wyszukiwania case/dictionary lub wywoła każdą z twoich funkcji podczas tworzenia bloku dictionary/case. Zapamiętaj to, ponieważ chcesz wywołać każdą funkcję tylko raz za pomocą stylu hash / align = "left" /
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()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-17 21:52:45
Jeśli szukasz extra-statement, jako "switch", zbudowałem moduł Pythona, który rozszerza Pythona. Nazywa się ESPY jako "Enhanced Structure for Python" i jest dostępna zarówno dla Pythona 2.x i Python 3.x.
Na przykład w tym przypadku polecenie switch może być wykonane za pomocą następującego kodu:
macro switch(arg1):
while True:
cont=False
val=%arg1%
socket case(arg2):
if val==%arg2% or cont:
cont=True
socket
socket else:
socket
break
, które można użyć w następujący sposób:
a=3
switch(a):
case(0):
print("Zero")
case(1):
print("Smaller than 2"):
break
else:
print ("greater than 1")
Więc ESPY Przetłumacz to w Pythonie jako:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-28 15:09:16
Nie znalazłem prostej odpowiedzi, której szukałem nigdzie w wyszukiwarce Google. Ale i tak to rozgryzłem. To bardzo proste. Postanowiłem go opublikować, a może zapobiec kilku zadrapaniom mniej na czyjejś głowie. Kluczem jest po prostu" in " i krotki. Oto zachowanie instrukcji switch z fall-through, w tym przypadkowe fall-through.
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)
Zapewnia:
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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-12 18:43:57
Znalazłem, że wspólna struktura przełącznika:
switch ...parameter...
case p1: v1; break;
case p2: v2; break;
default: v3;
Można wyrazić w Pythonie w następujący sposób:
(lambda x: v1 if p1(x) else v2 if p2(x) else v3)
Lub sformatowane w jaśniejszy sposób:
(lambda x:
v1 if p1(x) else
v2 if p2(x) else
v3)
Zamiast instrukcji, wersja Pythona jest wyrażeniem, które ocenia do wartości.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-29 17:25:57
Stosowane przeze mnie rozwiązania:
Kombinacja 2 z zamieszczonych tutaj rozwiązań, która jest stosunkowo łatwa do odczytania i obsługuje domyślne.
result = {
'a': lambda x: x * 5,
'b': lambda x: x + 7,
'c': lambda x: x - 2
}.get(whatToUse, lambda x: x - 22)(value)
Gdzie
.get('c', lambda x: x - 22)(23)
Wyszukuje "lambda x: x - 2"
w dict i używa go z x=23
.get('xxx', lambda x: x - 22)(44)
Nie znajduje go w dict i używa domyślnego "lambda x: x - 22"
z x=44
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-23 16:27:48
# 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-24 01:17:46
Zrobiłem (stosunkowo) elastyczne i wielokrotnego użytku rozwiązanie do tego. Można go znaleźć na GitHub jako Ten gist. Jeśli wynik funkcji przełącznika można wywołać, jest on wywoływany automatycznie.
Spodobała mi się odpowiedź Marka Biesa
Ponieważ zmienna x
musi być użyta dwa razy, zmodyfikowałem funkcje lambda NA bez parametru.
I have to run with results[value](value)
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: zauważyłem, że mogę używać None
type ze słownikami. Więc to emuluje switch ; case else
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:36
Większość odpowiedzi tutaj są dość stare, a zwłaszcza te zaakceptowane, więc wydaje się, że warto uaktualnić.
Po pierwsze, oficjalnyPython FAQ obejmuje to i zaleca łańcuch elif
dla prostych przypadków i dict
dla większych lub bardziej złożonych przypadków. Sugeruje również zestaw metod visit_
(styl używany przez wiele frameworków serwerowych) w niektórych przypadkach:
def dispatch(self, value):
method_name = 'visit_' + str(value)
method = getattr(self, method_name)
method()
FAQ wspomina również PEP 275 , który został napisany, aby uzyskać oficjalną decyzję raz na zawsze na dodawanie instrukcji switch w stylu C. Jednak PEP został przeniesiony do Pythona 3 i został oficjalnie odrzucony jako osobna propozycja, PEP 3103. Odpowiedź brzmiała, oczywiście, nie-ale dwa PEPs mają linki do dodatkowych informacji, jeśli jesteś zainteresowany przyczynami lub historią.
Jedna rzecz, która pojawiła się wiele razy (i można zobaczyć w PEP 275, mimo że została wycięta jako prawdziwa rekomendacja) jest taka, że jeśli naprawdę przeszkadza Ci posiadanie 8 linijek kod do obsługi 4 przypadków, a 6 linii, które masz w C lub Bash, zawsze możesz napisać to:
if x == 1: print('first')
elif x == 2: print('second')
elif x == 3: print('third')
else: print('did not place')
Nie zachęca do tego PEP 8, ale jest czytelny i nie jest zbyt unidiomatyczny.
W ciągu ponad dziesięciu lat od odrzucenia PEP 3103, kwestia deklaracji przypadków w stylu C, a nawet nieco mocniejszej wersji w Go, została uznana za martwą; za każdym razem, gdy ktoś wspomina o tym na Pythonie-ideas lub-dev, odnosi się do starej decyzji.
Jednak idea pełnego dopasowania wzorców w stylu ML pojawia się co kilka lat, zwłaszcza, że języki takie jak Swift i Rust przyjęły ją. Problem polega na tym, że trudno jest uzyskać wiele korzyści z dopasowania wzorców bez algebraicznych typów danych. Podczas gdy Guido sympatyzował z tym pomysłem, nikt nie wpadł na propozycję, która bardzo dobrze pasuje do Pythona. (Możesz przeczytać mój 2014 strawman dla przykładu.) Może się to zmienić wraz z dataclass
w 3.7 i kilkoma sporadycznymi propozycjami mocniejszego enum
do obsługi typy sum, lub z różnymi propozycjami dla różnych rodzajów oświadczeń-wiązań lokalnych (jak PEP 3150 , lub zestaw propozycji obecnie omawianych na-pomysły). Ale do tej pory tak nie było.
Istnieją również okazjonalnie propozycje dopasowania stylu Perla 6, co jest w zasadzie miszmasz wszystkiego, od elif
przez regex po Przełączanie typu single-dispatch.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-10 06:13:39
def f(x):
return 1 if x == 'a' else\
2 if x in 'bcd' else\
0 #default
Krótki i łatwy do odczytania, ma wartość domyślną i obsługuje wyrażenia zarówno w warunkach, jak i wartościach zwrotnych.
Jest jednak mniej wydajny niż rozwiązanie ze słownikiem. Na przykład Python musi przeskanować wszystkie warunki przed zwróceniem wartości domyślnej.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-05 20:05:12
Myślę, że najlepszym sposobem jest użycie idiomów języka python, aby Twój kod był testowany . Jak pokazano w poprzednich odpowiedziach, używam słowników, aby wykorzystać struktury Pythona i język i zachować kod "case" izolowany w różnych metodach. Poniżej znajduje się Klasa, ale możesz użyć bezpośrednio modułu, globali i funkcji. Klasa posiada metody, które mogą być testowane z izolacją . W zależności od potrzeb możesz bawić się statycznymi metodami i atrybutami też.
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)
Można skorzystać z tej metody używając również klas jako kluczy z "__choice_table". W ten sposób można uniknąć nadużywania isinstance i zachować wszystko czyste i testowalne.
Przypuśćmy, że musisz przetworzyć wiele wiadomości lub pakietów z sieci lub Twojego MQ. Każdy pakiet ma swoją własną strukturę i swój kod zarządzania (w sposób ogólny). Z powyższym kodem można zrobić coś takiego:
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)
Więc złożoność nie jest spread w przepływie kodu, ale jest renderowany w strukturze kodu .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-20 14:54:43
Zrobiłem to małe i czyste rozwiązanie
result = {
'case1': foo1,
'case2': foo2,
'case3': foo3,
'default': default,
}.get(option)()
Gdzie foo1(), foo2 (), foo3() i default () są funkcjami
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-17 05:10:40
Definiowanie:
def switch1(value, options):
if value in options:
options[value]()
Pozwala na użycie dość prostej składni, z przypadkami połączonymi w mapę:
def sample1(x):
local = 'betty'
switch1(x, {
'a': lambda: print("hello"),
'b': lambda: (
print("goodbye," + local),
print("!")),
})
Próbowałem na nowo zdefiniować przełącznik w sposób, który pozwoliłby mi pozbyć się " lambda:", ale się poddałem. Podkręcanie definicji:
def switch(value, *maps):
options = {}
for m in maps:
options.update(m)
if value in options:
options[value]()
elif None in options:
options[None]()
Pozwoliło mi odwzorować wiele przypadków na ten sam kod i podać domyślną opcję:
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")
})
Każdy replikowany przypadek musi znajdować się w swoim własnym słowniku; switch() konsoliduje słowniki przed wyszukaniem wartość. Nadal jest brzydszy niż bym chciał, ale ma podstawową wydajność korzystania z haszowanego wyszukiwania na wyrażeniu, a nie pętli przez wszystkie klucze.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-25 18:23:33
Byłem trochę zdezorientowany po przeczytaniu odpowiedzi, ale to wszystko wyjaśniło:
def numbers_to_strings(argument):
switcher = {
0: "zero",
1: "one",
2: "two",
}
return switcher.get(argument, "nothing")
Ten kod jest analogiczny do:
function(argument){
switch(argument) {
case 0:
return "zero";
case 1:
return "one";
case 2:
return "two";
default:
return "nothing";
}
}
Sprawdź źródło , aby dowiedzieć się więcej o mapowaniu słownika do funkcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-19 11:49:28
Rozwiązaniem, którego używam, które również korzysta ze słowników, jest:
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)()
Ma to tę zaletę, że nie próbuje Oceniać funkcji za każdym razem, a ty po prostu musisz się upewnić, że funkcja zewnętrzna otrzymuje wszystkie informacje, których potrzebują funkcje wewnętrzne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-06 16:45:58
Zainspirowany tą niesamowitą odpowiedzią . Nie wymaga zewnętrznego kodu. Nie testowane. Przewrócenie nie działa prawidłowo.
for case in [expression]:
if case == 1:
do_stuff()
# Fall through
# Doesn't fall through INTO the later cases
if case in range(2, 5):
do_other_stuff()
break
do_default()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-26 21:44:57
Jeśli nie martwisz się utratą podświetlenia składni wewnątrz pakietu case, możesz wykonać następujące czynności:
exec {
1: """
print ('one')
""",
2: """
print ('two')
""",
3: """
print ('three')
""",
}.get(value, """
print ('None')
""")
Gdzie value
jest wartością. W C będzie to:
switch (value) {
case 1:
printf("one");
break;
case 2:
printf("two");
break;
case 3:
printf("three");
break;
default:
printf("None");
break;
}
Możemy również utworzyć funkcję pomocniczą w tym celu:
def switch(value, cases, default):
exec cases.get(value, default)
Więc możemy użyć go w ten sposób dla przykładu z jednym, dwoma i trzema:
switch(value, {
1: """
print ('one')
""",
2: """
print ('two')
""",
3: """
print ('three')
""",
}, """
print ('None')
""")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-25 22:56:30
Rozszerzając na odpowiedź Grega Hewgilla - możemy zamknąć słownik-rozwiązanie używając dekoratora:
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
To może być następnie używane z @case
-dekorator
@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
Dobra wiadomość jest taka, że zostało to już zrobione w NeoPySwitch - module. Po prostu zainstaluj za pomocą pip:
pip install NeoPySwitch
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:42