2012-07-26 17 views
10

Próbuję znaleźć najlepszy sposób na rozszerzenie zmiennej klasy. Mam nadzieję, że przykład metody, którą do tej pory wymyśliłem, jasno to wyjaśni.Właściwości klasy Pythona

class A(object): 
    foo = ['thing', 'another thing'] 

class B(A): 
    foo = A.foo + ['stuff', 'more stuff'] 

Staram się więc, aby podklasa dziedziczyła i rozszerzała zmienną klasy rodzica. Powyższa metoda działa, ale wydaje się nieco kludgey. Jestem otwarty na wszelkie sugestie, w tym osiągnięcie czegoś podobnego przy użyciu zupełnie innego podejścia.

Oczywiście mogę nadal korzystać z tej metody, jeśli zajdzie taka potrzeba, ale jeśli jest lepszy sposób, chciałbym ją znaleźć.

+6

co chodzi o 'foo' że musi być [klasa własności] (http: // stackoverflow.com/questions/128573/), a nie tylko właściwość instancji? (Zważywszy, że listy są zmienne, możesz * zmienić * właściwość klasy na czas '__init__'.) – kojiro

+7

IMHO, co dla mnie wygląda dobrze (i nie mogę wymyślić bardziej czystego sposobu wykonania) to). Nawiasem mówiąc, nazwałbym te "atrybuty klas", a nie "właściwości klas", ponieważ właściwość jest czymś innym (zwykle tworzonym przez wbudowaną funkcję/dekorator 'property'). – mgilson

+0

@kojiro On nie odnosi się do tego rodzaju właściwości, on po prostu oznacza atrybuty. – Julian

Odpowiedz

8

Przydałby się metaklasa:

class AutoExtendingFoo(type): 

    def __new__(cls, name, bases, attrs): 
     foo = [] 
     for base in bases: 
      try: 
       foo.extend(getattr(base, 'foo')) 
      except AttributeError: 
       pass 
     try: 
      foo.extend(attrs.pop('foo_additions')) 
     except KeyError: 
      pass 
     attrs['foo'] = foo 
     return type.__new__(cls, name, bases, attrs) 

class A(object): 
    __metaclass__ = AutoExtendingFoo 
    foo_additions = ['thing1', 'thing2'] 
    # will have A.foo = ['thing1', 'thing2'] 

class B(A): 
    foo_additions = ['thing3', 'thing4'] 
    # will have B.foo = ['thing1', 'thing2', 'thing3', 'thing4'] 

class C(A): 
    pass 
    # will have C.foo = ['thing1', 'thing2'] 

class D(B): 
    pass 
    # will have D.foo = ['thing1', 'thing2', 'thing3', 'thing4'] 
+2

Ładnie, ale narusza zasadę najmniejszej niespodzianki. Może jednak przypisz do '__add_to_foo__', udając, że dziedziczymy puste' foo' z 'obiektu'. – chepner

+0

@chepner To jest ładniejsze. Zmienię to ... –

1

I ostatecznie pójdzie do właściwości instancji. (jeśli mam rację, nie są one zobowiązane do statycznego dla sprawy ?!)

>>> class A: 
...  @property 
...  def foo(self): 
...   return ['thin', 'another thing'] 
... 
>>> class B(A): 
...  @property 
...  def foo(self): 
...   return super().foo + ['stuff', 'thing 3'] 
... 
>>> B().foo 
['thin', 'another thing', 'stuff', 'thing 3'] 
+0

To nie jest szczególnie skuteczne, jeśli często korzystasz z tych danych. Musisz wykonać wyszukiwanie atrybutów na "A", a następnie utworzyć nową listę i dołączać do niej za każdym razem, gdy wchodzisz na 'B.foo'. Plus nadal masz problem, że każda podklasa musi zdefiniować właściwość tak, że pobiera 'super(). Foo'. A jeśli jakiekolwiek przyszłe klasy dziedziczą z wielu klas posiadania foo, szybko otrzymujesz wiele trudnych do naśladowania problemów. –

Powiązane problemy