[Python] @classmethod ed ereditarietà

enrico franchi enrico.franchi a gmail.com
Sab 5 Gen 2013 00:41:24 CET


2013/1/4 Pietro Battiston <me a pietrobattiston.it>

ho da poco scoperto "classmethod", e mi stanno parecchio simpatico.


A me non tanto... non tanto classmethod, poverino, tanto quel retrogusto di
'sono sicuro di non avere ciccato il design' che un un uso massiccio di
suddetta feature lascia in bocca. Un uso moderato e' perfettamente ok e
risolve una serie di questioni importanti. Pero' quando ci si trova con
troppi metodi di classe qualche domanda uno se la deve porre.

Ho
> però trovato un piccolo ostacolo riguardo all'ereditarietà.


Meglio! Meno ereditarieta', meno lavoro! ;)


> Per i metodi
> "normali", posso fare il classico:
>
> class Base(object):
>     def fai_qualcosa(self):
>         ...
>         return result
>
> class Derivata(Base):
>     def fai_qualcosa(self):
>         primo_passo = Base.fai_qualcosa( self )
>         ...
>         return result
>

"Basta" fra virgolette. Nel senso che c'e' un lungo dibattito fra
Base.method e super(Derived, self).method.
In teoria il modo "corretto" sarebbe l'ultimo: corretto in questo senso
vuole dire che "per fare quella cosa li, Guido ha aggiunto quella feature
nel linguaggio". Ci sono pareri autorevoli in favore del piu' blando
Base.method(self).

Personalmente io uso quasi sempre super. Mi rompe meno se faccio
refactoring. Ed e' piu' robusto se si fanno cose strambe con
l'ereditarieta'.

Ma per i classmethod non trovo qualcosa di ugualmente comodo ed
> elegante, nel senso che
>
> class Base(object):
>     @classmethod
>     def fai_qualcosa(cls):
>         ...
>         return result
>
> class Derivata(Base):
>     @classmethod
>     def fai_qualcosa(cls):
>         primo_passo = Base.fai_qualcosa( cls )
>         ...
>         return result
>
>
> chiaramente protesta ("Base.fai_qualcosa" prende un solo argomento, che
> è per l'appunto sempre "Base"). Quindi l'unica alternativa che mi viene
> in mente è dare a "fai_qualcosa" un argomento opzionale "cls_effettiva".
> C'è qualcosa di meglio che mi sfugge?
>

Beh, per come funzionano i descrittori mi sembra assolutamente inevitabile
che "fai_qualcosa" sia un bound della classe.

In [146]: Base.foo
Out[146]: <bound method type.foo of <class '__main__.Base'>>

Viceversa, super "fa la cosa giusta", perche' e' "piu' sveglio".

Dalla doc di super:

super(type, type2) -> bound super object; requires issubclass(type2, type)
Typical use to call a cooperative superclass method:

class C(B):
    def meth(self, arg):
        super(C, self).meth(arg)

Poi se interessa si puo' andare a vedere nel dettaglio che fa il buon
super...

-- 
.
..: -enrico
-------------- parte successiva --------------
Un allegato HTML è stato rimosso...
URL: <http://lists.python.it/pipermail/python/attachments/20130105/9fb36c3e/attachment.html>


Maggiori informazioni sulla lista Python