|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Oct 2006
Messaggi: 1105
|
[Python] duck typing e semantica
ciao a tutti, volevo intavolare una discussione su un aspetto di Python che ancora non ho ben metabolizzato: la mancanza dell'overloading dei metodi.
Dato che in Python un metodo è identificato univocamente dal suo nome (all'interno di un dato namespace), non è consentito l'overloading dello stesso. Poco male, visto che Python si affida al duck typing. Ma sorgono comuqnue due ordini di problemi. Il primo problema nasce quando il duck typing non può funzionare perché oggetti di tipo diverso espongono una stessa funzioalità tramite metodi aventi nomi differenti. In tal caso ho due strade: 1. verificare il tipo del parametro 2. verificare quale metodo viene esposto dal parametro Il primo approccio ha il difetto di obbligare il programmatore a elencare esplicitamente TUTTI i tipi che il metodo dovrà supportare. Il secondo approccio è un'estensione del concetto di duck typing e, in quanto tale, credo sia preferibile, ma apre la strada al secondo problema a cui accennavo poco fa: cosa succede quando due oggetti diversi possiedono metodi con lo stesso nome e diverse liste di parametri? Ad esempio, un oggetto QuerySet in Django è simile a un oggetto di tipo list, ma mentre QuerySet ha un metodo count() che restituisce il numero di elementi nel QuerySet, il metodo count di list necessita di un parametro e restituisce il numero di volte in cui tale parametro compare nella lista. In un caso del genere, la semplice verifica della presenza del metodo count non può funzionare. Veniamo alle domande: 1. esiste un approccio che permetta di gestire entrambe le situazioni senza dover cambiare idioma? 2. è stato introdotto in python 3.0 un metodo per gestire queste situazioni? (mi pare ne avesse accennato raymond hettinger alla PyCon2 italia, forse le annotation?) |
|
|
|
|
|
#2 | |||
|
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Quote:
Quote:
Al limite potresti estendere uno dei due oggetti in modo da sovrascrivere il metodo count di uno e farlo funzionare esattamente come l'altro. Ma in questo modo se passi l'oggetto a una funzione che si aspetta il count originale, non funzionerebbe più nulla. La soluzione è di avere un'interfaccia comune che implementano entrambe le classi, e personalmente mi affiderei alla funzione built-in len(), che già funziona con le liste restituendo il numero di elementi che contiene. Estenderei poi QuerySet in questo modo: Codice:
class MyQuerySet(QuerySet):
def __len__(self):
return QuerySet.count(self)
Codice:
class MyQuerySet(QuerySet): __len__ = QuerySet.count A questo punto utilizzerei len() per entrambi i tipi di oggetto. Quote:
Tutto ciò ovviamente se ho capito cosa intendevi. Se ti servono altre informazioni, chiedi pure.
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
|||
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Oct 2006
Messaggi: 1105
|
ciao cesare, grazie per le risposte.
Avevo già preso in considerazione le tue soluzioni, il problema è che a volte sono decisamente overkill rispetto al problema da risolvere. Inoltre nel cas di django il problema è che QuerySet non si crea esplicitamente ma viene restituito attraverso dei factory method quindi oltre a estendere QuerySet dovrei modificare il framework per restituire il nuovo tipo esteso... Per le annotazioni, probabilmente avevo frainteso il discorso di Raymond. Grazie per l'aiuto, prezioso come sempre |
|
|
|
|
|
#4 | |||
|
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Quote:
Soluzione 1. Supposto che la classe QuerySet si trovi nel modulo x.y.z: Codice:
x.y.z.QuerySet.__len__ = x.y.z.QuerySet.count Soluzione2. Supponiamo che foo() sia la funzione che torni un'istanza di QuerySet: Codice:
Records = x.y.z.foo() Records.__len__ = Records.count Solo che la prima lo fa alla classe base, per cui una volta aggiunto ad essa verrà automaticamente ereditato da tutte le istanze di QuerySet, incluse quelle già create. La seconda soluzione invece lo aggiunge soltanto all'istanza appena creata. Una parziale riscrittura della seconda soluzione potrebbe essere questa: Codice:
def DecoratedQS(Instance): Instance.__len__ = Instance.count return Instance Records = DecoratedQS(x.y.z.foo()) Codice:
def foo(): Instance = x.y.z.foo() Instance.__len__ = Instance.count return Instance Records = foo() Quote:
Per curiosità: ma hai sentito Raymond alla scorsa PyCon2, oppure da qualche altra parte? Quote:
Come vedi soluzioni ai problemi ne esistono diverse (probabilmente ce ne saranno altre). La cosa bella che trovo in Python è che grazie alla sua dinamicità è possibile crearne di utili e interessanti che con altri linguaggi nemmeno mi sarei sognato di fare, in quanto non possibili o estremamente macchinosi. Il tutto mantenendo il codice sempre pulito ed elegante. Per lo meno, questa è l'impressione che ho dopo un po' di anni che ci lavoro.
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
|||
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Oct 2006
Messaggi: 1105
|
mmm... queste ultime soluzioni mi piacciono particolarmente: sono concise e molto chiare. Grazie molte!
Si, ho sentito Raymond alla PyCon2, ma all'epoca della conferenza avevo alle spalle solo una settimana di python per cui molto probabilmente ho frainteso alcuni discorsi su python 3.0 Da allora python è il linguaggio che uso ogni giorno al lavoro (devo ringraziare il mio capo e un collega per questo |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
E' esattamente lo stesso motivo che mi ha portato a "innamorarmi" di Python, che ormai uso quasi esclusivamente per lavorare. Con lui ho ritrovato il piacere di programmare in maniera "creativa".
Comunque alla PyCon2 c'ero pure io, ed ero quello che ha sparato a Raymond le ultime tre domande di fila e a cui volevano strappare via il microfono.
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: Oct 2006
Messaggi: 1105
|
Quote:
|
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 23:54.




















