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
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)
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.
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.
Ah bon... Quelle formation ? À quel moment tu en parles ?
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.
Merci beaucoup pour toutes ces réponses! J'ai repris le code à zéro et le problème est réglé.
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.
In vino Veritas, in Aqua Sanitas
typage structurel ftw
In vino Veritas, in Aqua Sanitas
typage structurel ftw
In vino Veritas, in Aqua Sanitas
typage structurel ftw
typage structurel ftw
typage structurel ftw
entwanne — @entwanne — Un zeste de Python — La POO en Python — Notions de Python avancées — Les secrets d'un code pythonique
In vino Veritas, in Aqua Sanitas