Partage
  • Partager sur Facebook
  • Partager sur Twitter

Probleme de "switch" en python

Problème utilisation de dictionnaire comme un "switch"

Sujet résolu
    28 juillet 2011 à 17:05:18

    Bonjour !

    Tout d'abord je tiens à vous féliciter pour ce site très bien fait.

    Voici la raison de mon post :

    J'ai déclaré un dictionnaire comme suit :

    dictSeasons = {"spring":range(4, 7), "summer":range(7, 10), "autumn":range(10, 13), "winter":range(1, 4)}
    


    Vous l'aurez deviné, en clé ce sont les saisons et en valeur la liste des mois de l'année correspondant

    Je vais simplifier dans ce post la fonction que je cherche à faire :

    #     la fonction doit retourner une liste de fichier en fonction de la saison mais simplifions en ca :
    # **options permet de recevoir un nombre inconnu de parametres nommés, qui seront stockés dans un dictionnaire
    def getListFileSeason(**options):
      # Pour chaque élément du dictionnaire je créé une variable associée
      for cle, valeur in options.items():
        exec(str(cle) + '=' + str(valeur))
      # je boucle sur la liste des mois
      for month in dictSeasons[season]:
        print month
    


    J'aimerais que cette fonction affiche la liste des mois de la liste.
    Si par exemple je fais un appel du style :

    getListFileSeason(season="spring")
    


    Cela doit me retourner

    4
    5
    6
    


    Mais cela me retourne une erreur du style :

    getListFileSeason(**options)
        for cle, valeur in options.items():
          exec(str(cle) + '=' + str(valeur))
    --> for month in dictSeasons[season]:
          print month
    
    KeyError: <function spring at 0x21c65f0>
    


    Voila si quelqu'un a une suggestion je le remercie ;)
    • Partager sur Facebook
    • Partager sur Twitter
      28 juillet 2011 à 17:29:57

      C'est ce qui arrive quand on utilise des comportements réflexifs de façon hasardeuse !
      Rends-toi compte que exec(str(cle) + '=' + str(valeur)) traitera "valeur" non pas comme une chaîne de caractère mais comme une variable.
      Tu devrais donc remplacer cette instruction par exec(str(cle) + '= "' + str(valeur)+'"') mais, dans l'idéal, je t'encourage à faire apparaître explicitement l'argument season et à éviter "exec".
      • Partager sur Facebook
      • Partager sur Twitter
        28 juillet 2011 à 17:47:39

        Ok c'est cool :)

        Merci pour les conseils je vais essayer de trouver une autre solution alors
        • Partager sur Facebook
        • Partager sur Twitter
          29 juillet 2011 à 10:30:39

          ça sert à quoi ?

          for cle, valeur in options.items():
              exec(str(cle) + '=' + str(valeur))
          
          • Partager sur Facebook
          • Partager sur Twitter

          Python c'est bon, mangez-en. 

            1 août 2011 à 16:07:34

            Citation : josmiley

            ça sert à quoi ?

            for cle, valeur in options.items():
                exec(str(cle) + '=' + str(valeur))
            


            Cela sert à créer une variable pour chaque élément du dictionnaire options.
            je trouvais que ça facilitait le codage après, puisque tu utilise les noms de variables.

            Dans mon exemple, cela permet d'utiliser la variable season directement, et non d'utiliser options["season"]

            Par exemple, pouvoir faire

            print season
            


            au lieu de faire

            print options["season"]
            


            Mais après réflexion, je trouve que ce n'est pas si intéressant que ça lol
            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              1 août 2011 à 16:23:54

              def getListFileSeason(**dico):
                  return [dictSeasons[i] for i in dico.values()][0]
                      
              
              dictSeasons = {"spring":range(4, 7), "summer":range(7, 10), "autumn":range(10, 13), "winter":range(1, 4)}
              
              for mois in getListFileSeason(season = "spring"):
                  print mois
              


              c'est les values() qui t'intéressent et pas les keys(), il a pas aimé parce-qu'il ne reconnaît pas la clé
              • Partager sur Facebook
              • Partager sur Twitter
                1 août 2011 à 16:33:16

                Je n'ai pas bien compris cette syntaxe fred1599,
                Est ce que tu pourrais la détailler un peu ?
                • Partager sur Facebook
                • Partager sur Twitter
                Anonyme
                  1 août 2011 à 16:38:51

                  En fait je pense que tu devrais revoir les dictionnaires et les "lists comprehension"

                  Sinon ton problème se règle bien plus facilement

                  def getListFileSeason(valeur):
                      for mois in dictSeasons[valeur]:
                          print mois
                  
                  dictSeasons = {"spring":range(4, 7), "summer":range(7, 10), "autumn":range(10, 13), "winter":range(1, 4)}
                  
                  getListFileSeason("spring")
                  


                  et ça a plus d'intérêt si tu donnes les noms des mois.

                  def getListFileSeason(valeur):
                      for mois in dictSeasons[valeur]:
                          print dico[mois]
                  
                  dictSeasons = {"spring":range(4, 7), "summer":range(7, 10), "autumn":range(10, 13), "winter":range(1, 4)}
                  
                  dico = {1: 'janvier', 2: 'fevrier', 3: 'mars', 4: 'avril', 5: 'mai',
                   6: 'juin', 7: 'juillet', 8: 'aout', 9: 'septembre', 10: 'octobre',
                   11: 'novembre', 12: 'decembre'}
                  
                  getListFileSeason("spring")
                  


                  On peut aussi utiliser les générateurs

                  def getListFileSeason(valeur):
                      return '\n'.join(dico[i] for i in dictSeasons[valeur])
                  
                  dictSeasons = {"spring":range(4, 7), "summer":range(7, 10), "autumn":range(10, 13), "winter":range(1, 4)}
                  
                  dico = {1: 'janvier', 2: 'fevrier', 3: 'mars', 4: 'avril', 5: 'mai',
                   6: 'juin', 7: 'juillet', 8: 'aout', 9: 'septembre', 10: 'octobre',
                   11: 'novembre', 12: 'decembre'}
                  
                  print getListFileSeason("spring")
                  


                  Voir wikipedia pour les listes compréhension

                  • Partager sur Facebook
                  • Partager sur Twitter
                    1 août 2011 à 17:09:55

                    Je te remercie pour ton aide, je comprend ta solution mais en fait season était un exemple, ce que je voulais faire, c'est mettre une variable inconnu nommée à la fin pour pouvoir ne pas se limiter aux saisons, mais aussi aux années, aux mois etc.

                    Donc l'idée c’était de faire quelque chose du genre,

                    #pour l'année
                    getListFile(year=2011)
                    #pour le mois
                    getListFile(month=02)
                    #pour la saison
                    getListFile(season="spring")
                    


                    Mais j'ai bien apprécié ton post sur les compréhension de listes,
                    J'avoue que je n'ai pas trop prêté attention aux compréhension de listes parce que cela ne fait pas longtemps que je me suis mis au Python :p

                    Je vais corriger cela dès que possible ;)
                    • Partager sur Facebook
                    • Partager sur Twitter
                      2 août 2011 à 16:12:32

                      Si tu tiens absolument à créer une variable pour ton projet, au lieu de faire un exec, ce qui est en général moche, tu peux utiliser globals()
                      Un exemple pour te montrer :

                      >>> globals()
                      {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}
                      >>> globals
                      <built-in function globals>
                      >>> globals()['foo'] = "bar"
                      >>> foo
                      'bar'
                      >>>
                      


                      Ça reste moche, mais c'est surtout histoire d'apprendre quelque chose. :)

                      N.B. : il y a la même chose avec locals() si tu es dans une classe, une fonction ou un truc quelconque qui utilise des variables locales.
                      Et n'oublie pas une chose : coder, c'est facile, programmer c'est difficile.
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Anonyme
                        2 août 2011 à 16:30:05

                        globals() n'est ni plus ni moins qu'un dictionnaire avec clés et valeurs

                        >>> dir(globals())
                        ['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values', 'viewitems', 'viewkeys', 'viewvalues']
                        


                        • Partager sur Facebook
                        • Partager sur Twitter
                          2 août 2011 à 19:16:42

                          Bonjour !

                          Je reviens vers vous parce que je sais que vous êtes tous super sympa et que vous allez gentillement m'aider :) lol

                          C'est toujours à propos de mon option,

                          J'aimerais pouvoir utiliser un dictionnaire comme un switch, c'est-à-dire, en fonction de la valeur d'une variable exécuter un bout de code spécifique

                          donc ça doit donner quelque chose du style :

                          #Les fonctions sont définis un peu plus dans le fichier
                          #listFile est la liste de fichier qu'il faut modifier
                          #rootPath est le chemin vers lequel chercher les fichiers
                          {'year': getListFileYear(listFile, rootPath, year),
                           'month': getListFileMonth(listFile, rootPath, month),
                           'season': getListFileSeason(listFile, rootPath, season),
                           'all': getListFileAll(listFile, rootPath)}[opt]
                          

                          Seulement voila, lorsque je lance le programme, cela me renvoi une erreur me disant que les variables ne sont pas définies (rootPath etc).
                          C'est vrai que certaines ne le sont pas et qu'elles ne le seront pas pendant tout le programme mais c'est l’intérêt justement de pouvoir exécuter une portion de code spécifique donc je n'ai pas besoin que toutes les variables soient définies, juste celles dont j'ai besoin pour l'exécution.
                          Je n'arrive pas bien à comprendre la syntaxe dans ce cas.

                          Est ce que quelqu'un aurait un exemple avec explication à me montrer ?

                          Même un exemple perso ca sera bien lol

                          Comme ca, cela m'évitera d'utiliser ce fichu exec() :)

                          Merci pour votre aide
                          • Partager sur Facebook
                          • Partager sur Twitter
                            2 août 2011 à 20:36:35

                            Si tu veux utiliser des variables qui ne sont pas définies, tu ne le peux pas. C'est aussi simple que ça, sinon d'où sortiraient les valeurs des variables ?
                            Tu as non pas un problème avec le python, mais un problème de conception du programme, et en créant des variables comme ça sans les définir « pour de vrai » avec des exec, tu as des effets de bord qui rendent le programme très difficile à déboguer, à comprendre, à maintenir, à développer… Et il est difficile pour toi d'expliquer ton problème et pour les autres de comprendre ton problème.
                            • Partager sur Facebook
                            • Partager sur Twitter
                              3 août 2011 à 10:56:09

                              Ok je vais repenser mon prog alors merci pour votre aide ;)
                              _____________________________________________________________________

                              Ca y est j'ai réussi !

                              Je vous donne la syntaxe de ma solution si cela intéresse quelqu'un ;)
                              #options est le dictionnaire qui récupère le paramètre nommé
                              #opt est une chaine correspondant à la clé du dictionnaire
                              try
                                {'year': getListFileYear,
                                 'month': getListFileMonth,
                                 'season': getListFileSeason}[opt](listFile, rootPath, options[opt])
                              except KeyError:
                                getListFileAll(listFile, rootPath)
                              

                              J'ai enfin compris comment cela fonctionnait lol
                              • Partager sur Facebook
                              • Partager sur Twitter

                              Probleme de "switch" en python

                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                              • Editeur
                              • Markdown