2009-03-13 5 views
8

Très bien, donc mon titre a été aspiré. Un exemple fonctionne mieux:Equivalent "Pythonic" pour la gestion des commutateurs et des comparaisons de chaînes multiples

input = 'check yahoo.com' 

Je veux analyser l'entrée, en utilisant le premier mot comme la « commande », et le reste de la chaîne en tant que paramètre. Voici la version simple de la façon dont mon esprit non-Pythonic est le coder:

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

J'aime Python parce qu'il rend les choses normalement compliquées en des choses assez simples. Je ne suis pas trop expérimenté avec ça, et je suis à peu près sûr qu'il y a une bien meilleure façon de faire ces choses ... d'une façon un peu plus pythonique. J'ai vu quelques exemples de personnes remplaçant des instructions switch avec des fonctions dicts et lambda, alors que d'autres personnes ont simplement recommandé if..else nests.

+0

Une question python-switch précédent: http://stackoverflow.com/questions/60208/replacements-for-switch-statement-in-python – monkut

+0

Par souci d'intérêt, vous voudrez peut-être consulter une ancienne proposition d'amélioration Python (PEP) qui a été rejetée a été mis en place pour inclure une déclaration de commutateur en Python: http://www.python.org/dev/peps/pep-3103/ –

Répondre

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

A la place de do_default, vous pouvez soit faire un [0] dans dispatch: et passer le a [0] à la valeur par défaut, ou simplement remplacer do_default par lambda arg: do_default (a [0], arg) - - De cette façon, vous obtenez la commande passée. –

+0

Vous pouvez remplacer les quatre dernières lignes par: dispatch.get (cmd, do_default) (arg) –

+0

@John: De cette façon, do_default n'obtiendra pas le cmd. –

0

Si vous êtes à la recherche d'une approche « pythonique » une doublure à ce que vous pouvez utiliser ceci:


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

Eh bien, cela ne simplifie certainement pas l'exemple de Tom, mais il prend ses 8 lignes de code et fait le même chose en une seule ligne. – adam

+0

à la deuxième glace, il a utilisé un elif. J'avais d'abord pensé qu'il utilisait un autre. J'ai besoin de réviser mon code. Désolé pour la confusion. – adam

+0

mec c'est si faux. votre dictionnaire a seulement "vérifier", comme si vous auriez besoin d'un dictionnaire pour choisir entre "vérifier" et "chercher" car une instruction "si" n'est pas suffisante! – hasen

3

Cela vous permet d'éviter de donner le nom de chaque commande deux fois; Les noms de fonctions sont utilisés presque directement comme noms de commande.

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

Cela peut même être meilleur en utilisant une méthode de gestion des erreurs comme valeur par défaut pour gettr (au lieu de None), donc vous n'avez pas à chercher explicitement des commandes inconnues – Ber

+0

J'ai pensé à faire ça, mais la fonction appelée ne fonctionne pas obtenir les mots [0] afin qu'il ne soit pas capable d'imprimer la commande inconnue dans le message d'erreur. –

4

Je suis assez sûr qu'il ya une meilleure façon de faire ces choses ... une façon plus pythonique.

Pas vraiment. Vous codez est simple, clair, évident et anglais.

j'ai vu quelques exemples de personnes qui remplacent leurs déclarations de commutation avec dicts et fonctions lambda,

Oui, vous les avez vus et ils ne sont pas claires, évidentes ou en anglais comme. Ils existent parce que certaines personnes aiment tordre leurs mains sur l'instruction de commutation.

alors que d'autres personnes ont simplement recommandé si..sose nids.

Correct. Ils travaillent. Ils sont simples, clairs, ...

Votre code est bon. Laisser seul. Passez.

0

Mépris, je viens de réaliser que ma réponse était semblable à celle des autres réponses - et apparemment il n'y a pas de clé de suppression :)

0

Variation sur @MizardX's answer:

from collections import defaultdict 

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