2017-04-13 1 views
11

Disons que nous avons une classe AnimalFamilier en Python:Rédaction d'une méthode de python qui fait référence à la fois l'instance et la classe

class Pet(object): 
    num_pets = 0 

    def __init__(self, name): 
     self.name = name 
     Pet.num_pets += 1 

    def speak(self): 
     print("My name's %s and the number of pets is %d" % (self.name, self.num_pets)) 

Je veux la méthode init pour créer une instance, mais également mettre à jour un attribut sur la classe. Existe-t-il une façon plus élégante de faire cela que le code ci-dessus? J'ai essayé de passer en self et cls à la méthode init, puis en faisant référence à cls au lieu de Pet où num_pets est incrémenté, mais cela n'a pas fonctionné.

+4

Je vois le code ci-dessus être assez élégant. Sauf si 'num_pets' est un attribut géré par classe. Je ne vois aucune raison évidente pourquoi considérer la nécessité d'utiliser une méthode de classe ici. – direprobs

Répondre

13

Vous pouvez utiliser un classmethod pour augmenter le nombre d'animaux:

class Pet(object): 
    num_pets = 0 

    def __init__(self, name): 
     self.name = name 
     self.incr_num_pets() 

    @classmethod 
    def incr_num_pets(cls): 
     cls.num_pets += 1 

Sinon, vous pouvez incrémenter num_pets sur type(self):

def __init__(self, name): 
    self.name = name 
    type(self).num_pets += 1 

si je trouve cette deuxième méthode pour être un peu moins élégant même si c'est moins typé.

+0

Merci @mgilson, j'aime votre première solution. Très lisible! – michberr

4

Dans votre cas, vous pouvez utiliser __new__ avec __init__:

class Pet(object): 
    num_pets = 0 

    def __new__(cls, *args, **kwargs): 
     cls.num_pets += 1 
     return object.__new__(cls) 

    def __init__(self, name): 
     self.name = name 
1

Vous pouvez accéder à propre classe en utilisant self.__class__, cela signifie que votre __init__ peut ressemble:

def __init__(self, name): 
    self.name = name 
    self.__class__.num_pets += 1 
+0

Nice one! Merci! – michberr