Mai mult
Piese de schimb pentru comutator declarație în Python?
Vreau să se scrie o funcție în Python, care se întoarce diferite valori fixe pe baza valorii de intrare de index.
În alte limbi mi-ar folosi un "comutator" sau " caz "declarație, dar Python nu pare a fi un "comutator" declarație. Ce sunt recomandate Python soluții în acest scenariu?
1719
44
Ai putea folosi un dicționar:
Daca'd ca implicite ai putea folosi dicționar
ia(cheie[, default])
metoda:Am'am plăcut întotdeauna de a face în acest fel
De aici
În plus față de dicționarul metode (care chiar imi place, BTW), puteți utiliza, de asemenea, dacă-elif-altcineva pentru a obține switch/case/default funcționalitate:
Aceasta, desigur, nu este identic cu switch/case - de tine nu poate fi toamna-prin fel de ușor ca și lăsând pe pauză; declarație, dar puteți avea o mult mai complicat de testare. Formatarea acestuia este mai frumos decât o serie de imbricate ifs, chiar dacă din punct de vedere funcțional, care's ceea ce este mai aproape de.
Preferata mea Python reteta pentru comutator/caz este:
Scurt și simplu pentru scenarii simple.
Compara cu 11+ linii de cod C:
Aveți posibilitatea să atribuiți chiar de mai multe variabile, cu ajutorul tupluri:
Utilizare:
Teste:
Preferata mea este un foarte frumos reteta. Te'll place foarte mult. L's cel mai apropiat I'am vazut la real comutator caz de declarații, mai ales în funcții.
``python clasa de comutare(obiect): def init(self, valoare): auto.valoare = valoare auto.toamna = False
def iter(self): """se Întoarcă meciul metodă o dată, apoi opri""" randament de sine.meci ridica StopIteration
def meci(auto, *args): """Indică dacă sau nu să introduceți un caz suite""" dacă auto.se încadrează sau nu args: return True elif auto.valoarea în args: # s-a schimbat pentru v1.5, vezi mai jos auto.toamna = True return True altceva: return False ``
Aici's un exemplu:
``python
Următorul exemplu este destul de mult exact caz de utilizare a unui dicționar,
dar este inclus pentru simplitatea sa. Rețineți că puteți include declarații
în fiecare suită.
v = 'ten' pentru cazul în comutatorul(v): dacă este cazul('o'): imprimare 1 pauza dacă este cazul('doi'): imprimare 2 pauza dacă este cazul('ten'): imprimare 10 pauza dacă este cazul('unsprezece'): imprimare 11 pauza dacă este cazul(): # implicit, ar putea, de asemenea, doar omite condiție sau 'dacă este Adevărat' print "altceva!"
Nu este nevoie pentru a rupe aici, l'll stop
rup este folosit aici să se uite la fel de mult ca un lucru real posibil, dar
elif este în general la fel de bine si mai concis.
Gol suites sunt considerate erori de sintaxă, deci intenționată toamna-through
ar trebui să conțină 'trece'
c = 'z' pentru cazul în comutatorul(c): dacă este cazul('un'): trece # este necesar numai dacă restul suite este gol dacă este cazul('b'): pass
...
dacă este cazul('y'): pass dacă este cazul('z'): print "c este scris cu litere mici!" pauza dacă este cazul('Un'): pass
...
dacă este cazul('Z'): print "c este majuscule!" pauza dacă este cazul(): # default print "nu știu ce c!"
Cum a sugerat de către Pierre Quentel, se poate extinde chiar și asupra
funcționalitatea clasic 'caz' declarație de potrivire mai multe
cazuri într-o singură lovitură. Acest lucru foarte mult beneficiile operațiuni cum ar fi
majuscule/litere mici exemplul de mai sus:
import string c = 'Un' pentru cazul în comutatorul(c): dacă este cazul(string.litere mici): # notă pentru despachetare ca argumente print "c este scris cu litere mici!" pauza dacă este cazul(*string.majuscule): print "c este majuscule!" pauza daca este cazul('!', '?', '.'): # normal argument trece stil, de asemenea, se aplică print "c este o propoziție terminator!" pauza dacă este cazul(): # default print "nu știu ce c!" ``
``python clasa de Comutare: def init(self, valoare): auto.valoare = valoare
def intre(self): reveni auto
def exit(self, tip, valoare, traceback): return False # Permite o traceback să apară
def call(self, *valori): reveni sine.valoarea în valori
din datetime import datetime
cu Comutatorul(datetime.astăzi().weekday()) după caz: dacă este cazul(0):
Utilizare de bază a comuta
de imprimare("urăsc zilele de luni atât de mult.")
Notă nu există nici o pauză nevoie de aici
elif caz(1,2):
Acest comutator sprijină, de asemenea mai multe condiții (într-o singură linie)
de imprimare("atunci Când este week-end va fi aici?") elif caz(3,4): de imprimare("week-end este aproape.") altceva:
Default-ar avea loc aici
de imprimare("Sa's distracție plăcută!") # N't caz de utilizare de exemplu scopuri ``
Nu's un model care l-am învățat de la Twisted cod Python.
Îl puteți folosi în orice moment aveți nevoie pentru a trimite pe un semn și executa extins bucată de cod. Într-o mașină de stat ar fi
state_
metode, și un dispecer de la sine.de stat. Acest comutator poate fi lesne extinsă de moșteniți din clasa de bază și definesc propriile
dometode. De multe ori ai castigat't chiar trebuie
do metodele din clasa de baza.Edit: cât de exact este că used
În caz de SMTP veți primi
ELICOPTER
din sârmă. Codul relevant (de la twisted/mail/smtp.py`, modificate pentru cazul nostru) arata ca acest lucruTe'll primi
' HELO foo.bar.com '
(sau s-ar putea obține'QUIT' " sau " 'RCPT TO: foo'
). Acest lucru este tokenized în "părți", ca['HELO', 'foo.bar.com']. Metoda actuală de căutare numele este luat de la
piese[0]`.(Original metodă este, de asemenea, numit
state_COMMAND
, pentru că se folosește același model pentru a implementa o mașină de stat, adicăgetattr(auto, 'state_' + auto.modul de)
)Las's spun nu't doriți să se întoarcă o valoare, dar doriți să utilizați metode care modifica ceva pe un obiect. Folosind abordarea menționat aici ar fi:
Ce se întâmplă aici este că python evaluează toate metodele în dicționar. Deci, chiar dacă valoarea ta este 'un', obiect va primi incrementat și decrementat cu x.
Soluție:
Deci, veți obține o listă care conține o funcție și argumentele sale. În acest fel, numai funcția pointer și lista argument obține revenit, nu evaluate. 'rezultat' evaluează apoi a revenit funcția de apel.
Am'm doar de gând să renunțe la cei doi cenți ai mei aici. Motivul nu e't un caz/comutator declarație în Python deoarece Python urmează principiul de 'Există doar un singur mod corect de a face ceva'. Deci, evident, ai putea veni cu moduri diferite de a recrea comutator/caz funcționalitate, dar Pythonic mod de a realiza acest lucru este în cazul în care/elif construct. ie
Am simțit PEP 8 meritat un semn aici. Unul dintre lucrurile frumoase despre Python este simplitatea si eleganta. Care este în mare măsură derivate din principiile noastre în PEP 8, inclusiv "Nu's doar un singur mod corect de a face ceva"
extinderea pe "dict ca comutator" ideea. dacă doriți să utilizați o valoare implicită pentru switch:
Dacă aveți un complicat caz de bloc puteți lua în considerare, folosind o funcție de căutare dicționar de masă...
Dacă te-ai't face acest lucru înainte de a fi o idee bună să-ți debugger și vezi exact cum dicționar arata de fiecare funcție.
NOTĂ: Nu nu utilizați "()" în cazul/dicționar de căutare sau se va apela fiecare dintre funcțiile fel de dicționar / caz de bloc este creat. Amintesc acest lucru pentru că vrei doar pentru a apela fiecare funcție o dată folosind un hash stil de căutare.
Daca're în căutarea extra-declarație, ca "comutator", am construit un modul python care se extinde Python. L's a numit ESPY ca "Îmbunătățită Structura de Python" si's disponibil pentru ambele Python 2.x și Python 3.x.
De exemplu, în acest caz, un comutator declarație ar putea fi realizată prin următorul cod:
care pot fi utilizate astfel:
deci espy traduce în Python ca:
Am constatat că o comună comutator structura:
poate fi exprimat în Python, după cum urmează:
sau formatate într-un mod mai clar:
În loc de a fi o declarație, versiunea python este o expresie care se evaluează la o valoare.
Am't găsi răspunsul simplu am fost în căutarea pentru oriunde de pe Google search. Dar mi-am dat seama oricum. L's într-adevăr destul de simplu. A decis sa-l postez si poate preveni mai puține zgârieturi pe altcineva's cap. Cheia este pur și simplu "în" și tupluri. Aici este comutator declarație de comportament cu toamna-prin, inclusiv ALEATOARE toamna-prin.
Oferă:
Cele mai multe dintre răspunsurile de aici sunt destul de vechi, și mai ales cele acceptate, astfel încât se pare că merită actualizarea.
În primul rând, oficial Python FAQ se referă la acest lucru, și recomandă
elif
lanț pentru cazuri simple șidict
mai mari sau mai complexe cazuri. Acesta sugerează, de asemenea, un set devisit_
metode (un stil folosit de multe server cadre) pentru unele cazuri:FAQ menționează, de asemenea, PEP 275, care a fost scris pentru a obține un oficial odată-și-pentru-toate deciziei privind adăugarea de C-comutator stil declarații. Dar PEP a fost, de fapt, amânată pentru Python 3, și a fost respinsă în mod oficial ca o propunere separată, PEP 3103. Răspunsul a fost, desigur, nu—dar cele două PEPs au link-uri către informații suplimentare daca're interesat de motivele sau istoria.
Un lucru care a venit de mai multe ori (și poate fi văzut în PEP 275, chiar dacă a fost tăiat ca un real recomandare) este că, dacă te're într-adevăr deranjat de a avea 8 linii de cod să se ocupe de 4 cazuri, față de cele 6 linii te'd au în C sau Bash, puteți scrie întotdeauna aceasta:
Asta e't mai exact încurajat de PEP 8, dar's ușor de citit și nu prea unidiomatic.
Peste mai mult de un deceniu de când PEP 3103 a fost respinsă, problema C-stil de caz declarații, sau chiar puțin mai puternica versiune în Go, a fost considerat mort, ori de câte ori cineva aduce pe python-idei sau -dev, au're menționate la vechea decizie.
Cu toate acestea, ideea de a completa ML-stil de potrivire de model apare la fiecare câțiva ani, în special de limbi, cum ar fi Swift și Rugina au adoptat-o. Problema este ca's greu pentru a obține mai mult utilizarea de potrivire de model fără algebrice tipuri de date. În timp ce Guido a fost simpatic la idee, nimeni nu's-a venit cu o propunere care se potrivește în Python foarte bine. (Puteți citi mea 2014 strawman pentru un exemplu.) Acest lucru ar putea schimba cu dataclass în 3.7 și unele sporadice propuneri pentru o mai puternic
enum
să se ocupe de suma tipuri, sau cu diverse propuneri pentru diferite tipuri de declarație-legături locale (cum ar fi PEP 3150, sau un set de propuneri discutate în prezent la idei). Dar, până acum, nu a't.Există, de asemenea, ocazional propuneri pentru Perl 6-stil de potrivire, care este de fapt un amestec de tot, de la
elif
a regex pentru o singură expediere de tip comutare.Soluțiile eu folosesc:
O combinație de 2 dintre soluțiile postate aici, care este relativ ușor de citit și acceptă valorile implicite.
în cazul în care
se uită în sus
"lambda x: x - 2" în dict si foloseste-l cu
x=23`nu't găsi în dict și utilizează implicit
"lambda x: x - 22" " cu " x=44
.