Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème avec exec au milieu d'une fonction

    31 décembre 2018 à 0:44:30

      Bonjour,

    J'aimerais utiliser la fonction exec au milieu d'une fonction pour créer une instance de classe dynamiquement. J'essaie le code ci-dessous mais il ne marche pas. Auriez-vous une idée pour le corriger ou des conseils à me donner? Merci d'avance. 

    Class Objet:
     def__init__(self,name):
       self.name = name
    
    k=[]
    def creerobjet(string):
      exec("objet"+str(len(k))+"=Objet(string)")
      exec("auxilliaire = objet"+str(len(k)))
      return auxilliaire
    
    print(creerobjet("Pomme"))

    Cela me sort l'erreur suivante: 

      File "brouillon", line 9, in creerobjet
        return auxilliaire
    NameError: name 'auxilliaire' is not defined
    



    • Partager sur Facebook
    • Partager sur Twitter

    In vino Veritas, in Aqua Sanitas

      31 décembre 2018 à 11:18:12

      Bonjour, cette technique ne rentre pas du tout dans la philosophie de Python. Pour ce qui est de la création de classe dynamique, c'est abordé dans la deuxième partie du chapitre sur les métaclasses dans le cours qui existe sur ce site : https://openclassrooms.com/fr/courses/235344-apprenez-a-programmer-en-python/233659-les-metaclasses

      Je te donne rapidement le code proposé :

      def creer_personne(personne, nom, prenom):
          """La fonction qui jouera le rôle de constructeur pour notre classe Personne.
          
          Elle prend en paramètre, outre la personne :
          nom -- son nom
          prenom -- son prenom"""
          
          personne.nom = nom
          personne.prenom = prenom
          personne.age = 21
          personne.lieu_residence = "Lyon"
      
      def presenter_personne(personne):
          """Fonction présentant la personne.
          
          Elle affiche son prénom et son nom"""
          
          print("{} {}".format(personne.prenom, personne.nom))
      
      # Dictionnaire des méthodes
      methodes = {
          "__init__": creer_personne,
          "presenter": presenter_personne,
      }
      
      # Création dynamique de la classe
      Personne = type("Personne", (), methodes)



      • Partager sur Facebook
      • Partager sur Twitter

      typage structurel ftw

        31 décembre 2018 à 14:01:20

        Merci beaucoup! Je vais essayer ta méthode et rafraîchir ma mémoire concernant les métaclasses et j'espère que mon code va fonctionner.
        • Partager sur Facebook
        • Partager sur Twitter

        In vino Veritas, in Aqua Sanitas

          31 décembre 2018 à 21:33:32

          Ce n'est pas ma méthode, remercie plutôt Vincent Le Goff.
          • Partager sur Facebook
          • Partager sur Twitter

          typage structurel ftw

            2 janvier 2019 à 0:29:10

            Sinon pour mon code, pourquoi ça me renvoie l'erreur indiquée?
            • Partager sur Facebook
            • Partager sur Twitter

            In vino Veritas, in Aqua Sanitas

              2 janvier 2019 à 12:02:34

              Bonjour, j'ai repris et remis ton code en forme :

              class Objet:
              	def __init__(self,name):
              		self.name = name
               
              k=[]
              
              def creerobjet(string):
              	exec("objet"+str(len(k))+"=Objet(string)")
              	exec("auxilliaire = objet"+str(len(k)))
              	breakpoint() # un ajout de ma part
              	return auxilliaire
               
              print(creerobjet("Pomme"))

              Je trouve la même erreur que toi, mais bizarrement, depuis l'interface de débogage ouverte par breakpoint j'arrive à accéder à l'objet auxilliaire.

              En remodelant le code, j'obtiens :

              class Objet:
              
              
              	indexes = set() # c'est plus rapide de chercher dans un set que dans une liste
              
              
              	@staticmethod
              	def get_free_index():
              
              		i = 0
              		while i in Objet.indexes: i += 1
              		return i
              
              	@staticmethod
              	def reserve_index(index):
              		Objet.indexes.add(index)
              
              	@staticmethod
              	def release_index(index):
              		Objet.indexes.remove(index)
              
              	def __init__(self, name, index):
              		self.name = name
              		self.index = index
              
              	def __str__(self):
              		"""
              		str(Objet("Pomme", 3))
              		doit donner :
              		"3: Pomme"
              		"""
              
              		return f"{self.index}: {self.name}"
              
              
              def creerobjet(string):
              
              	index = Objet.get_free_index()
              	Objet.reserve_index(index)
              	# ce système permet de s'assurer qu'index est à chaque fois différent
              	# même si en fait c'est plutôt inutile.
              	# du coup il ne faut pas oublier de faire Objet.release_index(objet.index)
              	# avant de supprimer objet, sinon on va se heurter à un problème de dépassement
              	# d'entier
              
              	nom_nouveau_objet = f"objet{index}"
              
              	exec(f"{nom_nouveau_objet} = Objet(\"{string}\", {index})")
              	exec(f"nouveau_objet = {nom_nouveau_objet}")
              
              	# breakpoint() plus nécessaire
              
              	return eval("nouveau_objet")
               
              print(creerobjet("Pomme"))
              

              Voilà : j'ai eu l'idée de passer par return eval("nouveau_objet") plutôt que par return nouveau_objet sans savoir que ça allait régler le problème. En tout cas ce code marche mais je ne sais pas pourquoi il faut utiliser eval.

              Cela doit être la raison pour laquelle on évite cette formation.

              • Partager sur Facebook
              • Partager sur Twitter

              typage structurel ftw

              Anonyme
                2 janvier 2019 à 14:47:11

                Pourquoi vous faites ça ? À quoi vous sert la fonction exec ici ?

                class Object:
                    def __init__(self, name):
                        self.name = name
                
                obj = Object("Pomme")
                
                # ...
                
                objects = []
                name = input("Name: ")
                while name:
                    objects.append(Object(name))
                    name = input("Name: ")
                
                • Partager sur Facebook
                • Partager sur Twitter
                  2 janvier 2019 à 16:14:32

                  Bonjour, j'ai indiqué à de multiples reprises que la formation utilisée à l'origine n'est pas en accord avec la philosophie de Python. Pour ma part, j'essayais juste de résoudre le problème de la variable non définie, qui me semblait particulièrement intrigant.
                  • Partager sur Facebook
                  • Partager sur Twitter

                  typage structurel ftw

                  Anonyme
                    2 janvier 2019 à 21:35:05

                    Ah bon... Quelle formation ? À quel moment tu en parles ? o_O

                    Edit: Oups, j'ai cru que tu parlais d'un cours... Mais du coup, l'erreur vient de la manière dont est interprété le code par Python ; au moment ou le code est pré-compilé, la variable définie dans exec n'existe pas dans le contexte de la fonction creerobjet.

                    -
                    Edité par Anonyme 2 janvier 2019 à 21:42:46

                    • Partager sur Facebook
                    • Partager sur Twitter
                      3 janvier 2019 à 11:47:23

                      Merci beaucoup pour cette précision, encore un truc que j'ai appris aujourd'hui.
                      • Partager sur Facebook
                      • Partager sur Twitter

                      typage structurel ftw

                        6 janvier 2019 à 11:51:01

                        En effet, pas besoin de s'encombrer avec de la création dynamique de classes ici, tout ce qui est nécessaire est une liste.

                        -
                        Edité par entwanne 6 janvier 2019 à 11:51:11

                        • Partager sur Facebook
                        • Partager sur Twitter
                          20 janvier 2019 à 20:09:21

                          Merci beaucoup pour toutes ces réponses! J'ai repris le code à zéro et le problème est réglé.
                          • Partager sur Facebook
                          • Partager sur Twitter

                          In vino Veritas, in Aqua Sanitas

                          Problème avec exec au milieu d'une fonction

                          × 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