Disons que j'ai cette classe:
me = Person("António") print(me.name) you = Person(1) print(you.name)
Si je veux instancier Person
, je peux faire:
class Person: def __init__(self, name): if type(name) == str: self.name = name
Mais que se passe-t-il si je souhaite instancier uniquement Person
si name
a le type str
?
J'ai essayé ceci:
me = Person("António")
Mais quand je le fais:
class Person: def __init__(self, name): self.name = name
J'obtiens ceci:
Donc tout ce qui se passe est:
name
est str
, l'instance a une méthode .name
name
n'est pas str
, l'instance n'a pas de méthode .name
Mais ce que je veux en fait, c'est arrêter complètement l'instanciation si name n'est pas une str
.
En d'autres termes, je souhaite qu'il soit impossible de créer un objet à partir de la classe Person
avec un str
name
.
Comment puis-je faire cela?
3 Réponses :
Que diriez-vous de:
class Person: def __init__(self, name): if type(name) == str: self.name = name else: raise Exception("name attribute should be a string")
Je l'ai essayé avec ça, et ça marche un peu. Mais je ne suis pas sûr que cela arrête l'instanciation, ou si l'instanciation se produit toujours, même si chaque fois que l'instance est appelée, une erreur est déclenchée.
Oui, cela arrête l'instanciation, essayez _p = Person (1)
puis essayez d'accéder à _p
, vous verriez qu'il n'est pas défini
Vous pouvez utiliser une fabrique qui vérifie les paramètres et renvoie un objet Person
si tout va bien, ou génère une erreur:
peut-être quelque chose dans la ligne suivante:
PersonNameError Traceback (most recent call last) <ipython-input-41-a23e22774881> in <module> 14 15 p = person_from_name('Antonio') ---> 16 p = person_from_name(123) <ipython-input-41-a23e22774881> in person_from_name(name) 11 p.name = name 12 return p ---> 13 raise PersonNameError('a name must be a string') 14 15 p = person_from_name('Antonio') PersonNameError: a name must be a string
Considérant que:
p = person_from_name(123) # <-- parameter name is not a string
lève une exception:
class PersonNameError(Exception): pass class Person: def __init__(self): self.name = None def person_from_name(name: str) -> Person: """Person factory that checks if the parameter name is valid returns a Person object if it is, or raises an error without creating an instance of Person if not. """ if isinstance(name, str): p = Person() p.name = name return p raise PersonNameError('a name must be a string') p = person_from_name('Antonio')
Bien que je ne sois pas sûr, cela semble être la meilleure solution. Je l'ai essayé et il fonctionne. Merci. Juste une chose, ne vous manquez-vous pas le paramètre "name" dans le constructeur de classe "Person"? Beacuse j'ai dû ajouter cela à votre code pour le faire fonctionner ...
Vous pourriez en effet avoir Person
accepter les paramètres, mais ma préférence n'est pas de: j'ai conçu la méthode __init__
pour ne prendre aucun paramètre, et initialiser les attributs à Aucun < / code>, afin de déléguer tous les travaux de construction de l'instance à l'usine.
Je peux accepter votre réponse, pas de problème. Mais je voulais juste m'en assurer avant de le faire: votre code n'a-t-il pas besoin du paramètre "name" dans le constructeur "Person"?
Comme expliqué dans mon premier commentaire, vous pourriez le faire, mais je préfère ne pas le faire. Person .__ init __ (self)
ne prend pas d'arguments (autres que self
), et les attributs sont initialisés à None dans Person .__ init__
Vous devez utiliser le modèle de conception d'usine
. Pour en savoir plus, cliquez ici . Pour faire simple:
Créez une classe / méthode qui vérifiera les conditions et ne retournera une nouvelle instance de classe que si ces conditions sont remplies.
@Sweeper Peut-être que ça marcherait, je ne sais pas. Mais idéalement, je voudrais imprimer quelque chose comme "Échec de l'instanciation. Le prénom n'est pas str". Mais oui, je suppose que ce serait une façon de faire. Mais où dans le code pourrais-je même signaler l'erreur?
Dans la branche
else
de votre instructionif
?