Klassenkonstanten in Python

128

In Python möchte ich, dass eine Klasse einige "Konstanten" (praktisch Variablen) hat, die in allen Unterklassen gemeinsam sind. Gibt es eine Möglichkeit, dies mit benutzerfreundlicher Syntax zu tun? Im Moment benutze ich:

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

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

und ich frage mich, ob es einen besseren Weg gibt, es zu tun oder einen Weg, es zu tun, ohne dann "Animal" schreiben zu müssen. vor den Größen. Vielen Dank! bearbeiten: vergessen zu erwähnen, dass Pferd von Tier erbt.

nodwj
quelle
16
Keine vollständige Antwort, aber wenn sich SIZESnichts ändert, verwenden Sie auf jeden Fall ein Tupel anstelle einer Liste. Wie so("Huge","Big","Medium","Small")
Jamylak
Sieht so aus, als ob Sie wirklich nach einer Aufzählung hier sind
Eric

Antworten:

141

Da Horsees sich um eine Unterklasse von handelt Animal, können Sie diese einfach ändern

print(Animal.SIZES[1])

mit

print(self.SIZES[1])

Sie müssen sich jedoch daran erinnern, dass SIZES[1]dies "groß" bedeutet. Wahrscheinlich können Sie Ihren Code verbessern, indem Sie Folgendes tun:

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

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

Alternativ können Sie Zwischenklassen schaffen: HugeAnimal, BigAnimal, und so weiter. Das wäre besonders hilfreich, wenn jede Tierklasse eine andere Logik enthält.

Betabandido
quelle
SIZE_BIG = ["BigOne", "BigTwo"] soll ich diese Art von Konstante verwenden.
Lova Chittumuri
17

Sie können erhalten SIZESmittels self.SIZES(in einer Instanz - Methode) oder cls.SIZES(in einer Klassenmethode).

In jedem Fall müssen Sie explizit angeben, wo Sie zu finden sind SIZES. Eine Alternative besteht darin, SIZESdas Modul mit den Klassen einzufügen. Anschließend müssen Sie alle Klassen in einem einzigen Modul definieren.

Fred Foo
quelle
Pferd ist in der Tat eine Unterklasse von Tier. Tatsächlich ist es durchaus möglich, self.SIZES [1] anstelle von Animal.SIZES [1] zu verwenden.
Betabandido
@betabandido: Das OP hat die Frage korrigiert. Aktualisiert die Antwort entsprechend.
Fred Foo
12
class Animal:
    HUGE = "Huge"
    BIG = "Big"

class Horse:
    def printSize(self):
        print(Animal.HUGE)
amit
quelle
Sie können auch über sich selbst zugreifen, z. "self.HUGE" oder "self.BIG". Dies würde nur intern innerhalb der Klasse funktionieren.
Cevaris
4

Wenn Sie die Antwort von betabandido erweitern, können Sie eine Funktion schreiben, um die Attribute als Konstanten in das Modul einzufügen:

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
quelle
print SIZE_BIGaußerhalb der Klasse wird das gleiche sein? Wird es editierbar sein Animal.SIZE_HUGE = 'Small'?
Kreuzfahrer