Discussione:
Somma di tuple omogenee
(troppo vecchio per rispondere)
lupino
2007-06-14 15:44:37 UTC
Permalink
Ciao a tutti,
ieri ho cercato (velocemente) su google un modo per sommare tra loro tuple
omogenee (es: coordinate bidimensionali), ma non ho trovato nulla.

Ho fatto una funzioncina che somma N tuple di questo tipo:

def sum_2d_coords(*args):
res = (0, 0)
for t in args:
res = (res[0] + t[0], res[1] + t[1])
return res

Funziona egregiamente, ma mi chiedevo se c'è un modo più "pythonico" per
risolvere il problema.. Che ne pensate?

Grazie in anticipo,
--
[ Andrea Spadaccini - a.k.a. lupino3 - GLUGCT - from Catania - ICQ : 91528290 ]
[ GPG ID: 5D41ABF0 - key on keyservers - Debian GNU / Linux - Kernel 2.6.18.4 ]
[ Linux Registered User 313388 - a(dot)spadaccini(at)catania(dot)linux(dot)it ]
[ I would love to change the world, but they won't give me the source code ]
Zarathustra
2007-06-14 15:58:21 UTC
Permalink
Post by lupino
Funziona egregiamente, ma mi chiedevo se c'è un modo più "pythonico" per
risolvere il problema.. Che ne pensate?
Non so se sia più pythonico o più veloce, però con la list
Post by lupino
q=[s[i]+t[i] for i in xrange(len(s))]
Alex Martelli
2007-06-14 16:11:15 UTC
Permalink
Post by lupino
Ciao a tutti,
ieri ho cercato (velocemente) su google un modo per sommare tra loro tuple
omogenee (es: coordinate bidimensionali), ma non ho trovato nulla.
res = (0, 0)
res = (res[0] + t[0], res[1] + t[1])
return res
Funziona egregiamente, ma mi chiedevo se c'è un modo più "pythonico" per
risolvere il problema.. Che ne pensate?
def sum_2d_coords(*args):
return tuple(sum(x[i] for x in args) for i in (0,1))


Alex
lupino
2007-06-14 16:46:29 UTC
Permalink
Ciao Alex,sz
Post by Alex Martelli
Post by lupino
Funziona 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 Zarathustra:

def sum_coords(*args):
return tuple(sum(x[i] for x in args) for i in xrange(0, len(x))

Ma mi chiedevo.. non c'è un modo per ridefinire l'operatore di somma in Python
per i tipi built-in?

In effetti non avrebbe molto senso definire la somma tra tuple, ma tra tuple
n-dimensionali di interi.. sì!

Altra domanda: la tua soluzione non funziona con python 2.3, giusto?

Grazie,
--
[ Andrea Spadaccini - a.k.a. lupino3 - GLUGCT - from Catania - ICQ : 91528290 ]
[ GPG ID: 5D41ABF0 - key on keyservers - Debian GNU / Linux - Kernel 2.6.18.4 ]
[ Linux Registered User 313388 - a(dot)spadaccini(at)catania(dot)linux(dot)it ]
[ Knowledge speaks, but wisdom listens. ]
Y3s
2007-06-14 17:33:45 UTC
Permalink
Post by lupino
Ciao Alex,sz
Post by Alex Martelli
Post by lupino
Funziona 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!
E' Python! ;-)
Post by lupino
Ma mi chiedevo.. non c'è un modo per ridefinire l'operatore di somma in Python
per i tipi built-in?
Cioè? Puoi ridefinire gli operatori per i tuoi tipi:

http://www.python.it/doc/Python-Docs/html/ref/numeric-types.html

Ma non capisco cosa intendi per "ridefinire l'operatore *per i tipi
built-in*"
Post by lupino
In effetti non avrebbe molto senso definire la somma tra tuple, ma tra tuple
n-dimensionali di interi.. sì!
Puoi derivare un tuo tipo da tuple e ridefinirne l'operatore __add__, ma
attenzione alla semantica quando fai queste cose
lupino
2007-06-14 17:41:53 UTC
Permalink
Ciao Y3s,
Post by Y3s
Post by lupino
Ma mi chiedevo.. non c'è un modo per ridefinire l'operatore di somma in
Python per i tipi built-in?
http://www.python.it/doc/Python-Docs/html/ref/numeric-types.html
Ma non capisco cosa intendi per "ridefinire l'operatore *per i tipi
built-in*"
Ridefinire l'operatore somma per due tuple di interi. Come in C++.
Ma credo che non sia possibile senza ricorrere alla derivazione...
Post by Y3s
Post by lupino
In effetti non avrebbe molto senso definire la somma tra tuple, ma tra tuple
n-dimensionali di interi.. sì!
Puoi derivare un tuo tipo da tuple e ridefinirne l'operatore __add__, ma
attenzione alla semantica quando fai queste cose
.. infatti!
Ci penserò, devo vedere se effettivamente il miglioramento di leggibilità
giustifica lo sforzo di riconversione di tutte le occorrenze delle tuple già
utilizzate.

Perché dici di stare attento alla semantica?
Se il tipo lo definisco io, so bene che semantica assegno all'operatore!

Grazie mille!
--
[ Andrea Spadaccini - a.k.a. lupino3 - GLUGCT - from Catania - ICQ : 91528290 ]
[ GPG ID: 5D41ABF0 - key on keyservers - Debian GNU / Linux - Kernel 2.6.18.4 ]
[ Linux Registered User 313388 - a(dot)spadaccini(at)catania(dot)linux(dot)it ]
[ Nothing is as easy as it looks ]
Y3s
2007-06-14 17:51:51 UTC
Permalink
Post by lupino
Ciao Y3s,
Post by Y3s
Post by lupino
Ma mi chiedevo.. non c'è un modo per ridefinire l'operatore di somma in
Python per i tipi built-in?
http://www.python.it/doc/Python-Docs/html/ref/numeric-types.html
Ma non capisco cosa intendi per "ridefinire l'operatore *per i tipi
built-in*"
Ridefinire l'operatore somma per due tuple di interi. Come in C++.
Ma credo che non sia possibile senza ricorrere alla derivazione...
Boh penso che forse qualche schifezza si possa fare, ma sarebbe appunto
una schifezza: se ti serve un tipo che faccia cose diverse, hai bisogno di
un nuovo tipo...
Post by lupino
Post by Y3s
Post by lupino
In effetti non avrebbe molto senso definire la somma tra tuple, ma tra tuple
n-dimensionali di interi.. sì!
Puoi derivare un tuo tipo da tuple e ridefinirne l'operatore __add__, ma
attenzione alla semantica quando fai queste cose
.. infatti!
Ci penserò, devo vedere se effettivamente il miglioramento di leggibilità
giustifica lo sforzo di riconversione di tutte le occorrenze delle tuple già
utilizzate.
Già
Post by lupino
Perché dici di stare attento alla semantica?
Se il tipo lo definisco io, so bene che semantica assegno all'operatore!
A volte non è immediata o univoca la semantica da dare a un'operatore.
Bisogna stare attenti, tutto qua :-)
Post by lupino
Grazie mille!
Y3s
2007-06-14 17:59:46 UTC
Permalink
Post by Y3s
Post by lupino
Ciao Y3s,
Post by Y3s
Post by lupino
Ma mi chiedevo.. non c'è un modo per ridefinire l'operatore di somma in
Python per i tipi built-in?
http://www.python.it/doc/Python-Docs/html/ref/numeric-types.html
Ma non capisco cosa intendi per "ridefinire l'operatore *per i tipi
built-in*"
Ridefinire l'operatore somma per due tuple di interi. Come in C++.
Ma credo che non sia possibile senza ricorrere alla derivazione...
Boh penso che forse qualche schifezza si possa fare, ma sarebbe appunto
una schifezza: se ti serve un tipo che faccia cose diverse, hai bisogno di
un nuovo tipo...
Ripensandoci, di certo puoi derivare un nuovo tipo e sostituire il nome
builtin "tuple" con la tua classe..però non te lo consiglio e se lo fai
nn dire che te l'ho suggerito io :-)
Alex Martelli
2007-06-14 18:28:27 UTC
Permalink
Post by lupino
Ciao Alex,sz
Post by Alex Martelli
Post by lupino
Funziona 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 lupino
Ma 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 lupino
In 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 lupino
Altra 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

Loading...