[Python] property polimorfica

Piergiuliano Bossi pgbossi a gmail.com
Mar 3 Giu 2014 15:07:55 CEST


Ciao a tutti,

Vorrei definire una property in una gerarchia che si comporta diversamente
in maniera polimorfica in funzione del tipo dell'oggetto su cui e'
invocata. Mi vengono in mente 3 modi per farlo:
1) trattare la property con getter/setter alla Java e fare l'override solo
dei comportamenti che cambiano => non pythonico, per cui direi proprio da
evitare (ma ha i suoi vantaggi, vedi sotto)
2) usare il costrutto property => old style, richiede per forza di essere
ridefinito nelle classi derivate, verboso
3) usare il decoratore @property => new style, analogo al precedente,
comunque richiede di ridefinire la property nelle classi derivate che ne
vogliono cambiare il comportamento

Ho messo alcuni esempi qua sotto. L'opzione #1 e' orrida, ma e' anche
quella che richiede meno copia e incolla. L'opzione 3 e' credo quella che
un pythonista si aspetterebbe, ma ha lo svantaggio di richiedere copia e
incolla e ridefinire comportamenti che sono gia' definiti sulla superclasse.

Ci sono altri modi? Oppure fondamentalmente ho sviscerato le possibilita'?

Grazie e ciao
Giuliano


******* Codice *******
asdrubale:property giuliano.bossi$ cat java-style.py
class Dad(object):
    def get_value(self):
        return self._value

    def set_value(self, value):
        self._value = value

    def __str__(self):
        return "value={}".format(self._value)


class Son(Dad):
    def set_value(self, value):
        super(Son, self).set_value(value*2)


def func(arg):
    arg.set_value(15)
    print(arg)


func(Dad())
func(Son())
asdrubale:property giuliano.bossi$ python java-style.py
value=15
value=30
asdrubale:property giuliano.bossi$ cat old-property.py
class Dad(object):
    def get_value(self):
        return self._value

    def set_value(self, value):
        self._value = value

    value = property(get_value, set_value)

    def __str__(self):
        return "value={}".format(self._value)


class Son(Dad):
    def set_value(self, value):
        super(Son, self).set_value(value*2)

    def get_value(self):
        return super(Son, self).get_value()

    # needed, not polymorphic
    value = property(get_value, set_value)

def func(arg):
    arg.value = 15
    print(arg)


func(Dad())
func(Son())
asdrubale:property giuliano.bossi$ python old-property.py
value=15
value=30
asdrubale:property giuliano.bossi$ cat new-property.py
class Dad(object):
    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        self._value = value

    def __str__(self):
        return "value={}".format(self._value)


class Son(Dad):
    @property
    def value(self):
        return Dad.value.fget(self)

    @value.setter
    def value(self, value):
        Dad.value.fset(self, value*2)


def func(arg):
    arg.value = 15
    print(arg)


func(Dad())
func(Son())
asdrubale:property giuliano.bossi$ python new-property.py
value=15
value=30
asdrubale:property giuliano.bossi$ python --version
Python 2.7.5

-- 
Piergiuliano Bossi
Blog: http://thinkingbox.wordpress.com/
Twitter: http://twitter.com/thinkingbox (English)
Twitter: http://twitter.com/scatolapensante (Italiano)
Google+: https://plus.google.com/u/0/108187981162465525118
-------------- parte successiva --------------
Un allegato HTML è stato rimosso...
URL: <http://lists.python.it/pipermail/python/attachments/20140603/78c7a4f8/attachment.html>


Maggiori informazioni sulla lista Python