Operacje na krotkach w Pythonie, takie jak suma

99

Czy jest tak, aby operacje krotek w Pythonie działały w ten sposób:

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

zamiast:

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

Wiem, że to działa, ponieważ metody __add__i __mul__są tak zdefiniowane. Więc jedynym sposobem byłoby ich przedefiniowanie?

Rodrigo
źródło

Odpowiedzi:

137
import operator
tuple(map(operator.add, a, b))
ironfroggy
źródło
4
Powiedziałbym, że jest to najbardziej pytoniczne rozwiązanie.
Matthew Schinckel
3
Tyle że map () jest częściowo przestarzała. Zobacz artima.com/weblogs/viewpost.jsp?thread=98196, aby zapoznać się z artykułem Guido, w którym wspomina się o tym, jak lepiej pisać mapę w formie listy.
Adam Parkin
Wyskakuje również, jeśli a & b nie zawierają tej samej liczby elementów lub nie można ich „dodać” (np .:map(operator.add, (1,2), ("3", "4"))
Adam Parkin
22
tuple([item1 + item2 for item1, item2 in zip(a, b)])byłoby odpowiednikiem rozumienia listy.
Adam Parkin
11
@AdamParkin, rozumienie generatora jest jeszcze lepsze tuple(item1 + item2 for item1, item2 in zip(a, b)).
Cristian Ciupitu
118

Korzystanie ze wszystkich wbudowanych ...

tuple(map(sum, zip(a, b)))
Tryptyk
źródło
2
Wydaje się, że jest to prostsza, lepsza odpowiedź. Dlaczego nie jest to akceptowane?
Marc Cenedella
15
jest dobrze, ale technicznie nie jest to, o co się prosi, ponieważ mapa zwraca listę, a nie krotkę ... więc:tuple(map(sum,zip(a,b))
Ben
3
Składnia jest mistyczna.
anatoly techtonik
2
Zaletą tego jest to, że możesz go rozszerzyć na:tuple(map(sum,zip(a,b, c))
Andy Hayden,
32

To rozwiązanie nie wymaga importu:

tuple(map(lambda x, y: x + y, tuple1, tuple2))
Boaz Shvartzman
źródło
2
To rozwiązanie jest również szybsze niż inne rozwiązanie bez importu, jednoliniowe ( map(sum, zip(a, b)))
Air
20

W pewnym sensie połączyliśmy dwie pierwsze odpowiedzi, z poprawką kodu ironfroggy, tak aby zwracała krotkę:

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)

Uwaga: używanie self.__class__zamiast w stuplecelu ułatwienia tworzenia podklas.

Dana
źródło
11

Zamiast mapy można użyć generatora. Wbudowana funkcja mapy nie jest przestarzała, ale jest mniej czytelna dla większości ludzi niż rozumienie listy / generatora / dyktowania, więc ogólnie nie zalecałbym używania funkcji mapy.

tuple(p+q for p, q in zip(a, b))
Jaehyun Yeom
źródło
6

proste rozwiązanie bez definicji klasy, które zwraca krotkę

import operator
tuple(map(operator.add,a,b))
DemonEye
źródło
6

Wszystkie rozwiązania generatorów. Nie jestem pewien wydajności (chociaż itertools jest szybki)

import itertools
tuple(x+y for x, y in itertools.izip(a,b))
Mikrofon
źródło
3

Tak. Ale nie możesz przedefiniować wbudowanych typów. Musisz je podklasy:

class MyTuple (krotka):
    def __add __ (siebie, inne):
         if len (self)! = len (other):
             podnieść ValueError ("długości krotki nie są zgodne")
         return MyTuple (x + y for (x, y) in zip (self, other))
Doug
źródło
ale wtedy nie możesz użyć składni krotki.
lotnisko
3

jeszcze prostsze i bez użycia mapy, możesz to zrobić

>>> tuple(sum(i) for i in zip((1, 2, 3), (3, 2, 1)))
(4, 4, 4)
LetsPlayYahtzee
źródło
1

Obecnie podklasuję klasę „krotki” do przeciążenia +, - i *. Uważam, że dzięki temu kod jest piękny, a jego pisanie jest łatwiejsze.

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
źródło
-1

W przypadku, gdy ktoś potrzebuje uśrednić listę krotek:

import operator 
from functools import reduce
tuple(reduce(lambda x, y: tuple(map(operator.add, x, y)),list_of_tuples))
ytutow
źródło