Operações de tupla em elementos do Python, como soma

99

Existe alguma maneira de fazer com que as operações de tupla em Python funcionem assim:

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

ao invés de:

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

Eu sei que funciona assim porque os métodos __add__e __mul__são definidos para funcionar assim. Então, a única maneira seria redefini-los?

Rodrigo
fonte

Respostas:

137
import operator
tuple(map(operator.add, a, b))
ironfroggy
fonte
4
Eu diria que esta é a solução mais pitônica.
Matthew Schinckel
3
Exceto que map () está semi-obsoleto. Veja artima.com/weblogs/viewpost.jsp?thread=98196 para um artigo de Guido onde menciona como o mapa é melhor escrito como uma compreensão de lista.
Adam Parkin
Também explodirá se a & b não contiverem o mesmo número de elementos ou não forem "adicionáveis" (ex:map(operator.add, (1,2), ("3", "4"))
Adam Parkin
22
tuple([item1 + item2 for item1, item2 in zip(a, b)])seria o equivalente a uma compreensão de lista.
Adam Parkin
11
@AdamParkin, as compreensões do gerador são ainda melhores tuple(item1 + item2 for item1, item2 in zip(a, b)).
Cristian Ciupitu
118

Usando todos os integrados ..

tuple(map(sum, zip(a, b)))
Tríptico
fonte
2
Esta parece ser a resposta mais simples e superior. Por que não é aceito?
Marc Cenedella 01 de
15
é bom, mas tecnicamente não é o que é pedido porque o mapa retorna uma lista, não uma tupla ... então:tuple(map(sum,zip(a,b))
Ben
3
A sintaxe é mística.
anatoly techtonik
2
A vantagem deste é que você pode estendê-lo para:tuple(map(sum,zip(a,b, c))
Andy Hayden
32

Esta solução não requer importação:

tuple(map(lambda x, y: x + y, tuple1, tuple2))
Boaz Shvartzman
fonte
2
Esta solução também é mais rápida do que a outra solução de uma linha sem importação ( map(sum, zip(a, b)))
Ar
20

Uma espécie de combinação das duas primeiras respostas, com um ajuste no código do ironfroggy para que ele retornasse uma 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 em self.__class__vez de stuplepara facilitar a subclasse.

Dana
fonte
18
from numpy import *

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

print a + b

array([4,4,4]).

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

Mike
fonte
7
Isso funcionará, mas é um pouco pesado importar numpy apenas para uma simples operação de adição.
11

A compreensão do gerador pode ser usada em vez do mapa. A função de mapa embutida não é obsoleta, mas é menos legível para a maioria das pessoas do que a compreensão de lista / gerador / dicionário, então eu recomendo não usar a função de mapa em geral.

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

solução simples sem definição de classe que retorna tupla

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

Toda solução de gerador. Não tenho certeza sobre o desempenho (embora os itertools sejam rápidos)

import itertools
tuple(x+y for x, y in itertools.izip(a,b))
Mike
fonte
3

Sim. Mas você não pode redefinir os tipos integrados. Você deve subclassificá-los:

classe MyTuple (tuple):
    def __add __ (self, other):
         se len (próprio)! = len (outro):
             aumentar ValueError ("comprimentos de tupla não correspondem")
         return MyTuple (x + y for (x, y) in zip (self, other))
Doug
fonte
mas você não pode usar a sintaxe de tupla.
aeroportoyh
3

ainda mais simples e sem usar o mapa, você pode fazer isso

>>> tuple(sum(i) for i in zip((1, 2, 3), (3, 2, 1)))
(4, 4, 4)
LetsPlayYahtzee
fonte
1

Atualmente, eu subclasse a classe "tupla" para sobrecarregar +, - e *. Acho que torna o código mais bonito e mais fácil escrevê-lo.

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)
user2012588
fonte
-1

Caso alguém precise calcular a média de uma lista de tuplas:

import operator 
from functools import reduce
tuple(reduce(lambda x, y: tuple(map(operator.add, x, y)),list_of_tuples))
ytutow
fonte