Stałe klasowe w Pythonie

128

W Pythonie chcę, aby klasa miała pewne „stałe” (praktycznie zmienne), które będą wspólne dla wszystkich podklas. Czy można to zrobić za pomocą przyjaznej składni? Obecnie używam:

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

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

i zastanawiam się, czy istnieje lepszy sposób na zrobienie tego lub sposób na zrobienie tego bez konieczności pisania „Animal”. przed rozmiarami. Dzięki! edycja: zapomniałem wspomnieć, że koń dziedziczy po zwierzęciu.

nodwj
źródło
16
Nie jest to pełna odpowiedź, ale jeśli SIZESnigdy się nie zmieni, zdecydowanie użyj krotki zamiast listy. Tak("Huge","Big","Medium","Small")
jamylak
Wygląda na to, że naprawdę szukasz tutaj wyliczenia
Eric

Odpowiedzi:

141

Ponieważ Horsejest to podklasa Animal, możesz po prostu zmienić

print(Animal.SIZES[1])

z

print(self.SIZES[1])

Mimo to musisz pamiętać, że SIZES[1]oznacza to „duży”, więc prawdopodobnie mógłbyś ulepszyć swój kod, wykonując coś takiego:

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

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

Alternatywnie, można utworzyć klasy pośrednich: HugeAnimal, BigAnimal, i tak dalej. Byłoby to szczególnie pomocne, gdyby każda klasa zwierząt miała inną logikę.

betabandido
źródło
SIZE_BIG = ["BigOne", "BigTwo"] powinienem używać tego typu stałej.
Lova Chittumuri
17

Możesz dostać się SIZESza pomocą self.SIZES(w metodzie instancji) lub cls.SIZES(w metodzie klasowej).

W każdym razie musisz wyraźnie określić, gdzie znaleźć SIZES. Alternatywą jest umieszczenie SIZESmodułu zawierającego klasy, ale wtedy musisz zdefiniować wszystkie klasy w jednym module.

Fred Foo
źródło
Koń jest rzeczywiście podklasą zwierzęcia. Właściwie jest całkowicie możliwe użycie self.SIZES [1] zamiast Animal.SIZES [1].
betabandido
@betabandido: OP poprawił pytanie. Odpowiednio zaktualizuje odpowiedź.
Fred Foo
12
class Animal:
    HUGE = "Huge"
    BIG = "Big"

class Horse:
    def printSize(self):
        print(Animal.HUGE)
dobrze
źródło
Możesz również uzyskać dostęp przez siebie, np. „self.HUGE” lub „self.BIG”. To działałoby tylko wewnętrznie w klasie.
cevaris
4

Rozwijając odpowiedź betabandido, możesz napisać funkcję, która wstrzyknie atrybuty jako stałe do modułu:

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
źródło
print SIZE_BIGpoza klasą będzie to samo? Czy będzie można go edytować Animal.SIZE_HUGE = 'Small'?
Crusader