Operaciones de tupla por elementos de Python como suma
Pregunta
¿Existe alguna forma de hacer que las operaciones de tuplas en Python funcionen así?
>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(4,4,4)
en lugar de:
>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(1,2,3,3,2,1)
Sé que funciona así porque el __add__
y __mul__
Los métodos están definidos para funcionar así.Entonces, ¿la única manera sería redefinirlos?
Solución
import operator
tuple(map(operator.add, a, b))
Otros consejos
Uso de todos los elementos integrados ..
tuple(map(sum, zip(a, b)))
Esta solución no requiere una importación:
tuple(map(lambda x, y: x + y, tuple1, tuple2))
Más o menos combinó las dos primeras respuestas, con un ajuste al código de ironfroggy para que devuelva una tupla:
import operator
class stuple(tuple):
def __add__(self, other):
return self.__class__(map(operator.add, self, other))
# obviously leaving out checking lengths
>>> a = stuple([1,2,3])
>>> b = stuple([3,2,1])
>>> a + b
(4, 4, 4)
Nota: usar self.__class__
en lugar de stuple
para facilitar la subclasificación.
from numpy import *
a = array( [1,2,3] )
b = array( [3,2,1] )
print a + b
da array([4,4,4])
.
Se podría usar la comprensión del generador en lugar del mapa. La función de mapa incorporada no es obsoleta, pero es menos legible para la mayoría de las personas que la comprensión de lista / generador / dictado, por lo que recomendaría no usar la función de mapa en general.
tuple(p+q for p, q in zip(a, b))
solución simple sin definición de clase que devuelve tupla
import operator
tuple(map(operator.add,a,b))
Toda la solución del generador. No estoy seguro del rendimiento (aunque itertools es rápido)
import itertools
tuple(x+y for x, y in itertools.izip(a,b))
Sí Pero no puede redefinir los tipos incorporados. Tienes que subclasificarlos:
class MyTuple(tuple): def __add__(self, other): if len(self) != len(other): raise ValueError("tuple lengths don't match") return MyTuple(x + y for (x, y) in zip(self, other))
aún más simple y sin usar el mapa, puedes hacerlo
>>> tuple(sum(i) for i in zip((1, 2, 3), (3, 2, 1)))
(4, 4, 4)
Actualmente subclasifico la " tupla " clase para sobrecargar +, - y *. Creo que hace que el código sea hermoso y que escribir el código sea más fácil.
class tupleN(tuple):
def __add__(self, other):
if len(self) != len(other):
return NotImplemented
else:
return tupleN(x+y for x,y in zip(self,other))
def __sub__(self, other):
if len(self) != len(other):
return NotImplemented
else:
return tupleN(x-y for x,y in zip(self,other))
def __mul__(self, other):
if len(self) != len(other):
return NotImplemented
else:
return tupleN(x*y for x,y in zip(self,other))
t1 = tupleN((1,3,3))
t2 = tupleN((1,3,4))
print(t1 + t2, t1 - t2, t1 * t2, t1 + t1 - t1 - t1)
(2, 6, 7) (0, 0, -1) (1, 9, 12) (0, 0, 0)
En caso de que alguien necesite promediar una lista de tuplas:
import operator
from functools import reduce
tuple(reduce(lambda x, y: tuple(map(operator.add, x, y)),list_of_tuples))