Post by lupinoCiao Alex,sz
Post by Alex MartelliPost by lupinoFunziona egregiamente, ma mi chiedevo se c'è un modo più "pythonico" per
risolvere il problema.. Che ne pensate?
return tuple(sum(x[i] for x in args) for i in (0,1))
Bello! A questo punto possiamo definire, prendendo spunto dal messaggio di
return tuple(sum(x[i] for x in args) for i in xrange(0, len(x))
Quello '0,' in xrange e` superfluo; inoltre, visto che len(x) non e`
certo enorme, conviene range piuttosto che xrange. Inoltre manca una
parentesi chiusa. Quindi, al netto:
return tuple(sum(x[i] for x in args) for i in range(len(x)))
Purtroppo questo non puo` funzionare perche` x non e` un identificatore
definito nell'espressione range(len(x)). [[x e` definito solo entro la
genexp che passi come argomento a sum!]]. Cambiare quindi in:
return tuple(sum(x[i] for x in args) for i in range(len(args[0])))
(c'e` ovviamente un'ipotesi implicita e non verificata che tutti gli
argomenti siano sequenze di lunghezza identica).
Post by lupinoMa mi chiedevo.. non c'è un modo per ridefinire l'operatore di somma in Python
per i tipi built-in?
No: in Python, se A e B sono di tipi builtin, per qualsiasi operatore X
il risultato di
A X B
e` _sempre_ noto e ben definito (compreso la possibilita` che sia un
errore); non rischi mai di vedere, che so,
(2,3) + (4,5)
e dover esplorare quantita` illimitate di codice per scoprire se qualche
furbetto ha fatto il furbetto, SAI sempre che il risultato e` SOLO ED
ESCLUSIVAMENTE (2,3,4,5).
Se vuoi un linguaggio, peraltro simile a Python in tanti rispetti, che
abbatte questo cruciale elemento di sicurezza nella lettura del codice,
prova Ruby. In Ruby, se vedi
2+2
non hai nessun modo di sapere, senza leggere TUTTO il codice del
programma, se questo sia 4, 22, o "cucusettete!!!", proprio perche` e`
_possibile_ in Ruby ridefinire la semantica degli operatori sui tipi
predefiniti. Secondo me e` una jattura, e mi dicono che IN PRATICA non
si usa MAI, e vorrei anche vedere... ma di conseguenza preferisco di
gran lunga usare un compilatore che schiaffeggia chi _provi_ a fare lo
spiritoso (in altri termini, secondo me il dinamismo di Ruby e`
eccessivo in questo tipo di cose, e se i Rubyisti dicono che si puo`
fare ma non si deve MAI fare mi pare che concordino con me). Ma se tu
pensi che alterare la semantica di 2+2 o (1,2)+(3,4) sia una FORZA del
linguaggio, ti troverai piu` contento in un linguaggio che te lo
permette (come Ruby) che in uno che te lo proibisce (come Python).
Attenzione naturalmente al fatto che se un qualsiasi modulo di libreria
che usi fa (1,2)+(3,4) aspettandosi ovviamente come risultato la
concatenazione (1,2,3,4), e tu alteri il comportamento dell'operatore +
sulle tuple, quel modulo si trovera` (4,6) [o "cucusettete" a tuo gusto]
e probabilmente causera` bug misteriosi e profondi che se sei fortunato
ti provocheranno crash immediati, ma se hai un minimo di scalogna ti
prenderanno ore e giorni per trovarli e rimediarli. "Effetti
collaterali" globali sono sempre una brutta bestia da questo punto di
vista, la peggiore delle jatture, ed e` ovvio che ridefinire il
significato di un operatore (che e` un oggetto globale) sui tipi
predefiniti (che sono oggetti globali) non puo` non essere un effetto,
appunto, globale.
Post by lupinoIn effetti non avrebbe molto senso definire la somma tra tuple, ma tra tuple
n-dimensionali di interi.. sì!
La somma fra tuple e` perfettamente definita e produce la loro
concatenazione, cosi` come la somma fra stringhe, la somma fra liste, e
via elencando i tipi che costituiscono *sequenze* (array.array nella
libreria standard di Python, ecc, ecc). Ovviamente questo vale sia che
le tuple abbiano la stessa lunghezza o meno, sia che contengano entrambe
interi o meno, ecc, ecc.
Post by lupinoAltra domanda: la tua soluzione non funziona con python 2.3, giusto?
In Python 2.3 non esistevano le genexp e quindi per "simularle" devi
usare invece delle listcomp, un poco piu` lente e goffe:
return tuple([sum([x[i] for x in args]) for i in (0,1)])
quelle parentesi quadre in piu` trasformano le genexp in listcomp e
quindi permettono a questo approccio di funzionare anche nell'antico
Python 2.3. Ma ovviamente, salvo esigenze archeologiche particolari,
sono meglio le genexp.
Alex