Constantes de clase en python

128

En python, quiero que una clase tenga algunas "constantes" (prácticamente variables) que serán comunes en todas las subclases. ¿Hay alguna manera de hacerlo con una sintaxis amigable? Ahora mismo uso:

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

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

y me pregunto si hay una mejor manera de hacerlo o una manera de hacerlo sin tener que escribir "Animal". antes de los tamaños. ¡Gracias! editar: olvidé mencionar que el caballo hereda de los animales.

nodwj
fuente
16
No es una respuesta completa, pero si SIZESnunca cambia, definitivamente use una tupla en lugar de una lista. Me gusta así("Huge","Big","Medium","Small")
jamylak
Parece que realmente estás buscando una enumeración aquí
Eric

Respuestas:

141

Como Horsees una subclase de Animal, solo puedes cambiar

print(Animal.SIZES[1])

con

print(self.SIZES[1])

Aún así, debe recordar que SIZES[1]significa "grande", por lo que probablemente podría mejorar su código haciendo algo como:

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

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

Como alternativa, puede crear clases intermedias: HugeAnimal, BigAnimaly así sucesivamente. Eso sería especialmente útil si cada clase de animales contendría una lógica diferente.

betabandido
fuente
SIZE_BIG = ["BigOne", "BigTwo"] debo usar este tipo de constante.
Lova Chittumuri
17

Puede acceder SIZESmediante self.SIZES(en un método de instancia) o cls.SIZES(en un método de clase).

En cualquier caso, tendrá que ser explícito sobre dónde encontrar SIZES. Una alternativa es colocar SIZESel módulo que contiene las clases, pero luego debe definir todas las clases en un solo módulo.

Fred Foo
fuente
Horse es de hecho una subclase de Animal. En realidad, es perfectamente posible usar self.SIZES [1] en lugar de Animal.SIZES [1].
betabandido
@betabandido: el OP corrigió la pregunta. Actualizará la respuesta en consecuencia.
Fred Foo
12
class Animal:
    HUGE = "Huge"
    BIG = "Big"

class Horse:
    def printSize(self):
        print(Animal.HUGE)
amit
fuente
También puedes acceder por tu cuenta, ej. "self.HUGE" o "self.BIG". Esto solo funcionaría internamente dentro de la clase.
cevaris
4

Ampliando la respuesta de betabandido, podría escribir una función para inyectar los atributos como constantes en el módulo:

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
Matthew Trevor
fuente
print SIZE_BIGfuera de clase será lo mismo? ¿Será editable Animal.SIZE_HUGE = 'Small'?
Cruzado