2010-05-22 4 views
0

Pour mon application, j'ai besoin d'imprimer une série de sorties, puis accepter les entrées de l'utilisateur. Quelle serait la meilleure façon de faire cela?Lecture d'une série d'entrées/sorties en Python

Comme:

print '1' 
x = raw_input() 

print '2' 
y = raw_input() 

Quelque chose comme ça, mais il se poursuivre pendant au moins 10 fois. Ma seule préoccupation avec ce qui précède est que cela compenserait une mauvaise lisibilité du code.

Comment dois-je faire? Devrais-je créer une fonction comme celle-ci:

def printOut(string): 
    print string 

Ou y a-t-il un meilleur moyen?

+1

Une amélioration serait le module readline pour l'entrée de l'utilisateur: http://docs.python.org/library/readline.html – miku

Répondre

2

Première note: raw_input() prend un argument facultatif ... une chaîne d'invite. En ce qui concerne la question plus générale, une approche simpliste consisterait à créer une classe qui définisse les éléments de votre formulaire et fournit les fonctions pour leur entrée, leur validation, et les manipulations ou sorties ultérieures.

Avec un tel cas de classe peuvent être créés (instancié) et collectées, stockées, etc.

Une telle approche ne doit pas plus compliqué que quelque chose comme:

#!/usr/bin/python 
# I use /usr/bin/env python; but making SO's syntax highlighter happy. 

class generic_form: 
    def __init__(self, element_list): 
     self.form_elements = element_list 
     self.contents= dict() 

    def fill_it_in(self): 
     for prompt in self.form_elements: 
      self.contents[prompt] = raw_input(prompt) 

    def get(self, item): 
     return self.contents[item] 

    def print_it(self): 
     for each in self.form_elements: 
      print each, self.contents[each] 

if __name__ == '__main__': 
    sample_fields = ("Given Name: ", 
        "Surname: ", 
        "Date of Birth: ", 
        "Notes: ") 

    example = generic_form(sample_fields) 

    print "Fill in my form:" 
    example.fill_it_in() 

    print 
    print "Please review your input:" 
    example.print_it() 

    # store(:%s, %s: %s" % (example.get('Surname: '), \ 
    # example.get('Given Name: '), example.get('Notes: ')) 

Le code principal est seulement une douzaine de lignes de long pour définir une classe de formulaire générique avec l'entrée et la fonctionnalité de sortie (et une méthode simple get() à des fins d'illustration supplémentaires).

Le reste de cet exemple crée simplement une instance et montre comment il pourrait être utilisé.

Parce que ma classe generic_form est générique, nous devons fournir une liste des noms de champs qui doivent être remplis. Les noms sont utilisés à la fois comme les noms des champs pour un accès ultérieur (voir la méthode get() pour un exemple) . Personnellement, je ne le ferais pas de cette façon, je fournirais une liste de noms de champs courts et des invites similaires à l'exemple de Marcelo.Cependant, je voulais que cet exemple particulier soit le plus court possible pour faire passer le point principal.

(Le commentaire à la fin serait un appel à une fonction hypothétique "store()" pour stocker cela pour la postérité, soit dit en passant).

C'est l'approche la plus minimale. Cependant, vous constaterez rapidement qu'il est beaucoup plus utile d'avoir une classe plus riche avec validation pour chaque champ, et des classes séparées qui mettent en forme et produisent des instances de cette manière de différentes manières, et différentes classes pour l'entrée. L'entrée "teletype" (fournie par la fonction intégrée Python raw_input()) est la plus grossière (principalement utile pour la simplicité et pour la possibilité de traiter les fichiers à l'aide de la redirection du shell). On pourrait aussi supporter le support GNU readline (déjà inclus en tant que bibliothèque standard en Python), le support de curses (également inclus), et on pourrait imaginer écrire du code HTML et du code CGI pour gérer les entrées web.

Couplage "raw_input()" et "print" dans notre classe signifierait plus de travail si jamais nous avions besoin ou voulions prendre en charge toute forme d'entrée ou de sortie autre que "terminal muet". Si nous créons une classe qui ne s'occupe que des données à recueillir, alors elle pourrait fournir une interface pour toute autre classe d'entrée pour obtenir la liste des invites avec des références aux fonctions "setter" (et peut-être un " drapeau requis "ou" facultatif "). Ensuite, n'importe quelle instance de n'importe quelle classe d'entrée pourrait demander la liste des entrées désirées/requises pour n'importe quelle forme ... présenter les invites, appeler les méthodes "setter" (qui retournent un booléen pour indiquer si les données fournies étaient valides), boucle trop mauvaise entrées sur les champs "obligatoires", offre d'ignorer les champs "facultatifs", etc. Notez que la logique pour afficher les invites, accepter les réponses, les relayer à l'objet de données via leurs méthodes setter, et gérer les entrées invalides et être le même pour de nombreux types de formulaires. Tout ce dont nous avons besoin est un moyen pour le formulaire de fournir la liste des invites et leurs fonctions de validation correspondantes (et nous devons nous assurer que toutes ces fonctions de validation ont la même sémantique --- en prenant les mêmes paramètres et ainsi de suite).

Voici un exemple de séparer le comportement d'entrée du stockage et la validation des champs de données:

#!/usr/bin/env python 

    class generic_form: 
     def __init__(self, element_list): 
      self.hints = list() 
      for each in element_list: 
       self.hints.append((each, each, self.store)) 
      self.contents= dict() 
     def store(self, key, data): 
      '''Called by client instances 
      ''' 
      self.contents[key] = data 
      return True 

     def get_hints(self): 
      return self.hints 

     def get(self, item): 
      return self.contents[item] 


    def form_input(form): 
     for each, key, fn in form.get_hints(): 
      while True: 
       if fn(key,raw_input(each)): 
        break 
       else: 
        keep_trying = raw_input("Try again:") 
        if keep_trying.lower() in ['n', 'no', 'naw']: 
         break 

    if __name__ == '__main__': 
     sample_fields = ("Given Name: ", 
         "Surname: ", 
         "Date of Birth: ", 
         "etc: ") 

     example = generic_form(sample_fields) 

     print "Fill in my form:" 
     form_input(example) 

     print 
     print "Please review your input:" 
     for i, x, x in example.get_hints(): 
      print example.get(i), 

Dans ce cas, la complication supplémentaire ne fait rien utile. Notre generic_form n'effectue aucune validation. Toutefois, cette même fonction d'entrée peut être utilisée avec n'importe quelle classe de données/formulaire fournissant la même interface. Cette interface, dans cet exemple, requiert uniquement une méthode get_hints() fournissant des tuples de référence "chaîne d'invite", clé de stockage et fonction de stockage, et une méthode store() qui doit renvoyer "Vrai" ou "Faux" et prendre des arguments pour la clé et les données pour être stocké.

Le fait que notre clé de stockage soit passée à notre entrée "client" en tant qu'élément opaque qui doit être renvoyé à travers ses appels à notre méthode store() est un peu subtile; mais il nous permet d'utiliser une fonction de validation unique pour plusieurs éléments de formulaire ... tous les noms peuvent être n'importe quelle chaîne, toutes les dates doivent passer un appel à time.strftime() ou à un analyseur tiers ... et ainsi de suite.

Le point principal est que je peux créer de meilleures classes de formulaires qui implémentent des méthodes de validation de données appropriées aux données collectées et stockées. L'exemple de saisie fonctionnera pour nos formes bêtes originales, mais il fonctionnera mieux avec les formulaires qui renvoient des résultats significatifs de nos appels à store() (Une meilleure interface entre les formulaires et la gestion des entrées peut fournir des invites "error" et "help" ainsi que invite courte "entrée" courte que nous montrons ici Un système plus complexe peut passer des objets "datum" à travers les méthodes get_hints().Cela exigerait que la classe de formulaires instancie de tels objets et stocke une liste d'entre eux à la place des tuples que je montre ici).

Un autre avantage est que je peux également écrire d'autres fonctions d'entrée (ou classes qui implémentent de telles fonctions) qui peuvent également utiliser cette même interface sous n'importe quelle forme. Ainsi, je pourrais écrire du rendu HTML et du traitement CGI qui pourraient utiliser toutes les formes développées sans modifier ma sémantique de validation des données.

(Dans cet exemple, j'utilise la méthode get_hints() comme indication pour ma fonction de sortie brute ainsi que pour mes entrées, ce que je fais simplement pour garder l'exemple simple. à partir de la gestion des sorties).

+0

Merci pour cette réponse géniale. – user225312

0

Si vous lisez dans plusieurs domaines, vous voudrez peut-être faire quelque chose comme ceci:

field_defs = [ 
    ('name', 'Name'), 
    ('dob' , 'Date of Birth'), 
    ('sex' , 'Gender'), 
    #... 
    ] 

# Figure out the widest description.  
maxlen = max(len(descr) for (name, descr) in field_defs) 

fields = {} 
for (name, descr) in field_defs: 
    # Pad to the widest description. 
    print '%-*s:' % (maxlen, descr), 
    fields[name] = raw_input() 

# You should access the fields directly from the fields variable. 
# But if you really want to access the fields as local variables... 
locals().update(fields) 

print name, dob, sex 
+0

Merci pour cela. – user225312

0

"10 fois ... une mauvaise lisibilité du code"

Pas vraiment. Vous devrez fournir quelque chose de plus complexe que cela.

20 lignes de code ne posent pratiquement aucun problème. Vous pouvez facilement écrire plus de 20 lignes de code en essayant de vous sauver de simplement écrire 20 lignes de code. Vous devez également lire la description de raw_input. http://docs.python.org/library/functions.html#raw_input

Il écrit une invite. Vos quatre lignes de code sont vraiment

x = raw_input('1') 
y = raw_input('2') 

Vous ne pouvez pas simplifier cela davantage.

+0

Je vois. J'ai oublié ce fait. Merci. – user225312