Constantes de classe em python

128

Em python, eu quero que uma classe tenha algumas "constantes" (praticamente variáveis) que serão comuns em todas as subclasses. Existe uma maneira de fazer isso com sintaxe amigável? Agora eu uso:

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

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

e estou me perguntando se existe uma maneira melhor de fazê-lo ou uma maneira de fazê-lo sem ter que escrever "Animal". antes dos tamanhos. Obrigado! editar: esqueceu de mencionar que o cavalo herda de animal.

nodwj
fonte
16
Não é uma resposta completa, mas se SIZESnunca mudar, use definitivamente uma tupla em vez de uma lista. Como assim("Huge","Big","Medium","Small")
jamylak 20/05
Parece que você está realmente depois de uma enumeração aqui
Eric

Respostas:

141

Como Horseé uma subclasse de Animal, você pode simplesmente mudar

print(Animal.SIZES[1])

com

print(self.SIZES[1])

Ainda assim, você deve se lembrar que SIZES[1]significa "grande", então provavelmente você pode melhorar seu código fazendo 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)

Alternativamente, você pode criar classes intermediárias: HugeAnimal, BigAnimale assim por diante. Isso seria especialmente útil se cada classe de animais contiver uma lógica diferente.

betabandido
fonte
SIZE_BIG = ["BigOne", "BigTwo"] devo usar esse tipo de constante.
Lova Chittumuri 13/08/19
17

Você pode acessá-lo SIZESpor meio de self.SIZES(em um método de instância) ou cls.SIZES(em um método de classe).

De qualquer forma, você terá que ser explícito sobre onde encontrar SIZES. Uma alternativa é colocar SIZESo módulo que contém as classes, mas você precisa definir todas as classes em um único módulo.

Fred Foo
fonte
Cavalo é de fato uma subclasse de Animal. Na verdade, é perfeitamente possível usar self.SIZES [1] em vez de Animal.SIZES [1].
Betabandido 20/05
@betabandido: o OP corrigiu a pergunta. Atualizará a resposta de acordo.
Fred Foo
12
class Animal:
    HUGE = "Huge"
    BIG = "Big"

class Horse:
    def printSize(self):
        print(Animal.HUGE)
amit
fonte
Além disso, você pode acessar via auto, ex. "self.HUGE" ou "self.BIG". Isso funcionaria apenas internamente dentro da classe.
Cevaris
4

Expandindo a resposta do betabandido, você pode escrever uma função para injetar os atributos como constantes no 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
fonte
print SIZE_BIGfora da aula será o mesmo? Será editável Animal.SIZE_HUGE = 'Small'?
Crusader