2009-03-13 17 views
8

OK, quindi il mio titolo è stato risucchiato. Un esempio funziona meglio:Equivalente "Pythonic" per la gestione dell'interruttore e più stringhe a confronto

input = 'check yahoo.com' 

voglio analizzare in ingresso, utilizzando la prima parola come il "comando", e il resto della stringa come parametro. Ecco la versione semplice di come la mia mente non è Pythonic codificarlo:

if len(input) > 0: 
    a = input.split(' ') 
    if a[0] == 'check': 
     if len(a) > 1: 
      do_check(a[1]) 
    elif a[0] == 'search': 
     if len(a) > 1: 
      do_search(a[1]) 

mi piace Python perché rende le cose complicate normalmente in cose piuttosto semplici. Non ne ho molta esperienza, e sono abbastanza sicuro che c'è un modo molto migliore per fare queste cose ... in qualche modo più pitoni. Ho visto alcuni esempi di persone che sostituiscono le istruzioni di commutazione con dicts e funzioni lambda, mentre altre persone hanno semplicemente consigliato se ... nidificare.

+0

una precedente interrogazione python-interruttore: http://stackoverflow.com/questions/60208/replacements-for-switch-statement-in-python – monkut

+0

Per interesse anche tu potresti voler controllare un vecchio (è stato rifiutato) Python Enhancement Proposal (PEP) che è stato messo insieme per includere un'istruzione switch in Python: http://www.python.org/dev/peps/pep-3103/ –

risposta

31
dispatch = { 
    'check': do_check, 
    'search': do_search, 
} 
cmd, _, arg = input.partition(' ') 
if cmd in dispatch: 
    dispatch[cmd](arg) 
else: 
    do_default(cmd, arg) 
+0

Invece di fare_default lì, potresti voler fare un if se [0] in dispatch: e passare l'a [0] al default, o semplicemente sostituire do_default con lambda arg: do_default (a [0], arg) - - In questo modo ottieni il comando passato. –

+0

È possibile sostituire le ultime quattro righe con: invio.get (cmd, do_default) (arg) –

+0

@John: In questo modo do_default non otterrà il cmd. –

0

Se siete alla ricerca di un approccio uno di linea 'divinatorio' a questo è possibile utilizzare questo:


def do_check(x): print 'checking for:', x 
def do_search(x): print 'searching for:', x 

input = 'check yahoo.com' 
{'check': do_check}.get(input.split()[0], do_search)(input.split()[1]) 
# checking for: yahoo.com 

input = 'search google.com' 
{'check': do_check}.get(input.split()[0], do_search)(input.split()[1]) 
# searching for: google.com 

input = 'foo bar.com' 
{'check': do_check}.get(input.split()[0], do_search)(input.split()[1]) 
# searching for: bar.com 
+0

Beh, certamente non semplifica l'esempio di Tom, ma prende le sue 8 linee di codice e fa il stessa cosa in una sola riga. – adam

+0

in secondo luogo, ha usato un elif. Inizialmente avevo pensato che usasse un altro. Ho bisogno di rivedere il mio codice. Dispiace per la confusione. Tizio – adam

+0

questo è così sbagliato. il tuo dizionario ha solo "controllo", come se fosse necessario un dizionario per scegliere tra "verifica" e "ricerca" perché un'istruzione "se" non è sufficiente! – hasen

3

Ciò consente di evitare di dare ogni nome di comando due volte; i nomi di funzioni sono usati quasi direttamente come nomi di comandi.

class CommandFunctions: 
    def c_check(self, arg): 
     print "checking", arg 

    def c_search(self, arg): 
     print "searching for", arg 

    def c_compare(self, arg1, arg2): 
     print "comparing", arg1, "with", arg2 

    def execute(self, line): 
     words = line.split(' ') 
     fn = getattr(self, 'c_' + words[0], None) 
     if fn is None: 
      import sys 
      sys.stderr.write('error: no such command "%s"\n' % words[0]) 
      return 
     fn(*words[1:]) 

cf = CommandFunctions() 
import sys 
for line in sys.stdin: 
    cf.execute(line.strip()) 
+0

Questo può essere anche meglio utilizzando un metodo di gestione degli errori come valore predefinito per gettr (anziché None), quindi non è necessario verificare esplicitamente i commands sconosciuti – Ber

+0

Ho pensato di farlo, ma la funzione chiamata non ottieni parole [0] in modo che non possa stampare il comando sconosciuto nel messaggio di errore. –

4

Sono abbastanza sicuro che c'è un modo molto migliore per fare queste cose ... qualche modo più divinatorio.

Non proprio. Il codice è semplice, chiaro, ovvio e simile all'inglese.

Ho visto alcuni esempi di persone che sostituiscono le istruzioni switch con dicts e funzioni lambda,

Sì, li ho visti e non sono chiare, evidenti o inglese-like. Esistono perché ad alcune persone piace torcere le mani sulla dichiarazione di commutazione.

mentre altre persone hanno semplicemente consigliato se ... nidificare.

Corretto. Lavorano. Sono semplici, chiari, ...

Il tuo codice è buono. Lascialo da solo. Vai avanti.

0

Ignorare, ho solo capito che la mia risposta era simile a una delle altre risposte - e apparentemente non c'è tasto di cancellazione :)

0

Variazione su @MizardX's answer:

from collections import defaultdict 

dispatch = defaultdict(do_default, check=do_check, search=do_search) 
cmd, _, arg = input.partition(' ') 
dispatch[cmd](arg)