2015-08-09 13 views
8

Mam klasy o nazwie Node który ma importance setter i getter, poniżej:Zastępowanie dziedziczną własność setter

class Node: 

    @property 
    def importance(self): 
     return self._importance 

    @importance.setter 
    def importance(self, new_importance): 
     if new_importance is not None: 
      new_importance = check_type_and_clean(new_importance, int) 
      assert new_importance >= 1 and new_importance <= 10 
     self._importance = new_importance 

Później, mam klasę Theorem która dziedziczy Node. Jedyna różnica między Theorem i Node, o ile dotyczy to importance, polega na tym, że Theorem musi mieć importance co najmniej 3.

Jak można Twierdzenie dziedzicząimportance seter, ale dodać na dodatkowym ograniczeniem, że importance >= 3?

starałem się zrobić to w ten sposób:

class Theorem(Node): 

    @importance.setter 
    def importance(self, new_importance): 
     self.importance = new_importance # hoping this would use the super() setter 
     assert self.importance >= 3 
+2

Zauważ, że możesz rozwiązać problem zupełnie inaczej poprzez posiadanie atrybutu klasy 'MIN_IMPORTANCE', który jest' 1' w 'Węzeł' i' 3' w 'Twierdzeniu'. – jonrsharpe

+0

Możliwy duplikat [Przesłanianie właściwości w pythonie] (http://stackoverflow.com/questions/7019643/overriding-properties-in-python) –

Odpowiedz

6

Można odwołać się do istniejącego majątku bezpośrednio przez klasę Node i używać setter metodę m.in., aby utworzyć nową właściwość z nim:

class Theorem(Node): 
    @Node.importance.setter 
    def importance(self, new_importance): 
     # You can change the order of these two lines: 
     assert new_importance >= 3 
     Node.importance.fset(self, new_importance) 

Spowoduje to utworzenie nowej właściwości klasy Theorem, która używa metody getter z Node.importance, ale zastępuje metodę ustawiającą inną. Tak właśnie działają właściwości: wywołanie usługi setter zwraca nową właściwość z niestandardowym ustawiaczem, który zwykle zastępuje starą właściwość.

Możesz dowiedzieć się więcej o działaniu właściwości, czytając this answer (i także pytanie).

+1

'TypeError: setter() przyjmuje dokładnie jeden argument (2 dane)'. Miałeś na myśli 'fset'? – jonrsharpe

+0

@jonrsharpe Podskoki, spróbuj teraz: P –

+1

Tak, znacznie lepiej i schludniej niż mój! – jonrsharpe

3

Jednym ze sposobów, aby to zrobić, wdrażając nową właściwość na Theorem pomocą Node getter, zapewniając nową metodę setter i wywołanie Node setter wyraźnie w niej:

class Theorem(Node): 

    def _set_importance(self, new): 
     Node.importance.fset(self, new) 
     assert self.importance >= 3 

    importance = property(Node.importance.fget, _set_importance) 

O ile jestem świadomy , nie można tego zrobić z super.


Per this bug report, można zrobić:

class Theorem(Node): 

    def _set_importance(self, new): 
     super(Theorem, Theorem).importance.fset(self, new) 
     assert self.importance >= 3 

    importance = property(Node.importance.fget, _set_importance) 

Jest to jednak wyraźnie nieco niewygodne; łatka pozwalająca na wydanie super() wydaje się być zaplanowana dla Pythona 3.5 (z powodu September 2015).

+0

Nie przekazuj 'self .__ class__' do' super() '. Całkowicie się zerwie, gdy podklasujesz z "Twierdzenia". – Kevin

+0

@Kevin to zrobi? Szybki test wskazuje, że przechodzi do 'Node.importance.fset' z instancji podklasy' Theorem'. – jonrsharpe

+0

ISTM, że 'super (TheoremSubclass, TheoremSubclass) .importance' zwróci obiekt utworzony w ostatnim wierszu. To powinno wytworzyć nieskończoną rekursję, gdy nazwiesz 'fset()'. – Kevin

1

Tutaj jest zupełnie inaczej rozwiązanie szerszego problemu, z dużo mniejszym faffing okolicy:

class Node: 

    MIN_IMPORTANCE = 1 
    MAX_IMPORTANCE = 10 

    @property 
    def importance(self): 
     return self._importance 

    @importance.setter 
    def importance(self, new_importance): 
     if new_importance is not None: 
      new_importance = check_type_and_clean(new_importance, int) 
      assert (new_importance >= self.MIN_IMPORTANCE and 
        new_importance <= self.MAX_IMPORTANCE) 
     self._importance = new_importance 


class Theorem(Node): 

    MIN_IMPORTANCE = 3 

    # and that's all it takes! 

Moim zdaniem, to wyraża:

The only difference between a Theorem and a Node , as far as importance is concerned, is that a Theorem must have an importance of at least 3 .

dużo jaśniej niż nadpisanie metody seter nieruchomości ma.


assert Zauważ, że jest powszechnie stosowany do testowania i debugowania, a nie jako część ogólnego przebiegu programu, a już na pewno nie o rzeczy, które można oczekiwać mógłby zdarzyć; patrz np. Best practice for Python Assert.