Opérations de tuple élément par élément Python comme sum
Question
Y a-t-il un moyen d'obtenir que les opérations de tuple en Python fonctionnent comme suit:
>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(4,4,4)
au lieu de:
>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(1,2,3,3,2,1)
Je sais que cela fonctionne comme ça parce que les méthodes __add__
et __mul__
sont définies pour fonctionner comme ça. Donc, le seul moyen serait de les redéfinir?
La solution
import operator
tuple(map(operator.add, a, b))
Autres conseils
Utilisation de tous les éléments intégrés ..
tuple(map(sum, zip(a, b)))
Cette solution ne nécessite pas d'importation:
tuple(map(lambda x, y: x + y, tuple1, tuple2))
En quelque sorte, les deux premières réponses ont été combinées, avec un ajustement du code d'Ironfroggy afin qu'il renvoie un tuple:
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)
Remarque: utilisez self.__class__
au lieu de stuple
pour faciliter les sous-classes.
from numpy import *
a = array( [1,2,3] )
b = array( [3,2,1] )
print a + b
donne array([4,4,4])
.
La compréhension du générateur pourrait être utilisée à la place de la carte. La fonction de carte intégrée n'est pas obsolète, mais elle est moins lisible pour la plupart des gens que la compréhension de liste / générateur / dict, je vous recommande donc de ne pas utiliser la fonction de carte en général.
tuple(p+q for p, q in zip(a, b))
solution simple sans définition de classe renvoyant le tuple
import operator
tuple(map(operator.add,a,b))
Toute la solution du générateur. Pas sûr de la performance (itertools est rapide, cependant)
import itertools
tuple(x+y for x, y in itertools.izip(a,b))
Oui. Mais vous ne pouvez pas redéfinir les types intégrés. Vous devez les sous-classer:
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))
encore plus simple et sans utiliser la carte, vous pouvez le faire
>>> tuple(sum(i) for i in zip((1, 2, 3), (3, 2, 1)))
(4, 4, 4)
Je sous-classe actuellement le " tuple & "; classe à surcharger +, - et *. Je trouve que cela rend le code plus beau et l’écriture plus facile.
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)
Au cas où quelqu'un aurait besoin de faire la moyenne d'une liste de n-uplets:
import operator
from functools import reduce
tuple(reduce(lambda x, y: tuple(map(operator.add, x, y)),list_of_tuples))