2013-04-03 22 views
19
class human(object): 
    def __init__(self, name=''): 
     self.name = name 

    @property 
    def name(self): 
     return self._name 

    @name.setter 
    def name(self, value): 
     self._name = value 

class superhuman(human): 
    @property 
    def name(self): 
     return 'super ' + name 

s = superhuman('john') 
print s.name 

# Doesn't work :("AttributeError: can't set attribute" 
s.name = 'jack' 
print s.name 

Desidero essere in grado di ignorare la proprietà ma essere in grado di utilizzare il setter del super genitore senza dover eseguire l'override del setter nella classe figlio.Getter overriding Python senza setter

È possibile questo pythonicaly?

risposta

33

Usa solo la .getter decoratore della proprietà originale:

class superhuman(human): 
    @human.name.getter 
    def name(self): 
     return 'super ' + self._name 

Si noti che è necessario utilizzare il nome completo per raggiungere il descrittore di proprietà originale sulla classe genitore.

Dimostrazione:

>>> class superhuman(human): 
...  @human.name.getter 
...  def name(self): 
...   return 'super ' + self._name 
... 
>>> s = superhuman('john') 
>>> print s.name 
super john 
>>> s.name = 'jack' 
>>> print s.name 
super jack 

L'oggetto property descrittore è solo uno oggetto, anche se può avere più metodi associati (il getter, setter e deleter). Le funzioni di decorazione .getter, .setter e .deleter fornite da un descrittore property esistente restituiscono una copia del descrittore stesso, con quello specifico metodo sostituito.

Quindi nel tuo classe base human quello che succede è che in primo luogo creare il descrittore con l'@property decoratore, quindi sostituire quel descrittore con uno che ha sia un getter e un setter con la sintassi . Ciò funziona perché i decoratori python sostituiscono la funzione decorata originale con lo stesso nome, in pratica esegue name = name.setter(name). Vedi How does the @property decorator work? per i dettagli su come tutto funziona.

Nella sottoclasse si utilizza semplicemente tale trucco per creare una nuova copia del descrittore con solo il getter sostituito.