Constantes de classe en python

128

En python, je veux qu'une classe ait des "constantes" (pratiquement, des variables) qui seront communes à toutes les sous-classes. Existe-t-il un moyen de le faire avec une syntaxe conviviale? En ce moment, j'utilise:

class Animal:
    SIZES=["Huge","Big","Medium","Small"]

class Horse(Animal):
    def printSize(self):
        print(Animal.SIZES[1])

et je me demande s'il existe une meilleure façon de le faire ou une façon de le faire sans avoir à écrire "Animal". avant les tailles. Merci! edit: j'ai oublié de mentionner que le cheval hérite de l'animal.

nodwj
la source
16
Pas une réponse complète mais si SIZESjamais ne change, utilisez définitivement un tuple au lieu d'une liste. Like so("Huge","Big","Medium","Small")
jamylak
On dirait que vous êtes vraiment après une énumération ici
Eric

Réponses:

141

Puisqu'il Horses'agit d'une sous-classe de Animal, vous pouvez simplement changer

print(Animal.SIZES[1])

avec

print(self.SIZES[1])

Néanmoins, vous devez vous rappeler que cela SIZES[1]signifie «gros», donc vous pourriez probablement améliorer votre code en faisant quelque chose comme:

class Animal:
    SIZE_HUGE="Huge"
    SIZE_BIG="Big"
    SIZE_MEDIUM="Medium"
    SIZE_SMALL="Small"

class Horse(Animal):
    def printSize(self):
        print(self.SIZE_BIG)

Sinon, vous pouvez créer des classes intermédiaires: HugeAnimal, BigAnimalet ainsi de suite. Ce serait particulièrement utile si chaque classe d'animaux contenait une logique différente.

betabandido
la source
SIZE_BIG = ["BigOne", "BigTwo"] dois-je utiliser ce type de constante.
Lova Chittumuri
17

Vous pouvez y accéder au SIZESmoyen de self.SIZES(dans une méthode d'instance) ou cls.SIZES(dans une méthode de classe).

Dans tous les cas, vous devrez être explicite pour savoir où trouver SIZES. Une alternative est de mettre SIZESdans le module contenant les classes, mais vous devez ensuite définir toutes les classes dans un seul module.

Fred Foo
la source
Le cheval est en effet une sous-classe des animaux. En fait, il est parfaitement possible d'utiliser self.SIZES [1] au lieu de Animal.SIZES [1].
betabandido
@betabandido: l'OP a corrigé la question. Mettra à jour la réponse en conséquence.
Fred Foo
12
class Animal:
    HUGE = "Huge"
    BIG = "Big"

class Horse:
    def printSize(self):
        print(Animal.HUGE)
amit
la source
Vous pouvez également accéder via self, ex. "self.HUGE" ou "self.BIG". Cela ne fonctionnerait qu'en interne au sein de la classe.
cevaris
4

En développant la réponse de betabandido, vous pouvez écrire une fonction pour injecter les attributs sous forme de constantes dans le module:

def module_register_class_constants(klass, attr_prefix):
    globals().update(
        (name, getattr(klass, name)) for name in dir(klass) if name.startswith(attr_prefix)
    )

class Animal(object):
    SIZE_HUGE = "Huge"
    SIZE_BIG = "Big"

module_register_class_constants(Animal, "SIZE_")

class Horse(Animal):
    def printSize(self):
        print SIZE_BIG
Matthieu Trevor
la source
print SIZE_BIGhors de la classe sera la même chose? Sera-ce modifiable Animal.SIZE_HUGE = 'Small'?
Crusader