Operaciones de tupla de elementos de Python como suma

99

¿Hay alguna forma de hacer que las operaciones de tupla en Python funcionen así?

>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(4,4,4)

en vez de:

>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(1,2,3,3,2,1)

Sé que funciona así porque los métodos __add__y __mul__están definidos para funcionar así. Entonces, ¿la única forma sería redefinirlos?

Rodrigo
fuente

Respuestas:

137
import operator
tuple(map(operator.add, a, b))
ironfroggy
fuente
4
Yo diría que esta es la solución más pitónica.
Matthew Schinckel
3
Excepto que map () está semi-obsoleto. Consulte artima.com/weblogs/viewpost.jsp?thread=98196 para ver un artículo de Guido en el que se menciona cómo se escribe mejor el mapa como una lista de comprensión.
Adam Parkin
También explota si a & b no contienen la misma cantidad de elementos, o no son "sumables" (por ejemplo:map(operator.add, (1,2), ("3", "4"))
Adam Parkin
22
tuple([item1 + item2 for item1, item2 in zip(a, b)])sería el equivalente a una lista de comprensión.
Adam Parkin
11
@AdamParkin, la comprensión del generador es aún mejor tuple(item1 + item2 for item1, item2 in zip(a, b)).
Cristian Ciupitu
118

Utilizando todos los elementos integrados ...

tuple(map(sum, zip(a, b)))
Tríptico
fuente
2
Esta parece ser la respuesta superior más simple. ¿Por qué no se acepta?
Marc Cenedella
15
es bueno, pero técnicamente no es lo que se pide porque el mapa devuelve una lista, no una tupla ... así que:tuple(map(sum,zip(a,b))
Ben
3
La sintaxis es mística.
anatoly techtonik
2
El beneficio de este es que puede extenderlo a:tuple(map(sum,zip(a,b, c))
Andy Hayden
32

Esta solución no requiere una importación:

tuple(map(lambda x, y: x + y, tuple1, tuple2))
Boaz Shvartzman
fuente
2
Esta solución también es más rápida que la otra solución de una sola línea sin importación ( map(sum, zip(a, b)))
Air
20

Una especie de combinación de las dos primeras respuestas, con un ajuste en el 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 en self.__class__lugar de stuplepara facilitar la subclasificación.

Dana
fuente
18
from numpy import *

a = array( [1,2,3] )
b = array( [3,2,1] )

print a + b

da array([4,4,4]).

Ver http://www.scipy.org/Tentative_NumPy_Tutorial

Miguel
fuente
7
Esto funcionará, pero es un poco pesado importar numpy solo para una simple operación de adición.
11

Se podría usar la comprensión del generador en lugar del mapa. La función de mapa incorporada no está obsoleta, pero es menos legible para la mayoría de las personas que la comprensión de listas / generadores / dict, por lo que recomendaría no usar la función de mapas en general.

tuple(p+q for p, q in zip(a, b))
Jaehyun Yeom
fuente
6

solución simple sin definición de clase que devuelve tupla

import operator
tuple(map(operator.add,a,b))
DemonEye
fuente
6

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))
Miguel
fuente
3

Si. Pero no puede redefinir los tipos integrados. Tienes que subclasificarlos:

clase MyTuple (tupla):
    def __add __ (yo, otro):
         if len (self)! = len (other):
             elevar ValueError ("las longitudes de tupla no coinciden")
         devuelve MyTuple (x + y para (x, y) en zip (self, other))
Doug
fuente
pero luego no puede usar la sintaxis de tupla.
airportyh
3

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)
LetsPlayYahtzee
fuente
1

Actualmente, hago una subclase de la clase "tupla" para sobrecargar +, - y *. Encuentro 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)
usuario2012588
fuente
-1

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))
ytutow
fuente