1
votes

Comment créer une classe dans laquelle l'instanciation ne se produit que si certaines conditions sont remplies?

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:

entrez la description de l'image ici

Donc tout ce qui se passe est:

  • Si name est str , l'instance a une méthode .name
  • Si 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?


2 commentaires

@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 instruction if ?


3 Réponses :


0
votes

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")


2 commentaires

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



1
votes

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') 


4 commentaires

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__



0
votes

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.


0 commentaires