Operasi tupel bijak dengan elemen Python seperti sum

99

Apakah ada cara untuk membuat operasi tupel dengan Python bekerja seperti ini:

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

dari pada:

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

Saya tahu ini berfungsi seperti itu karena __add__dan __mul__metode didefinisikan untuk bekerja seperti itu. Jadi satu-satunya cara adalah dengan mendefinisikannya kembali?

Rodrigo
sumber

Jawaban:

137
import operator
tuple(map(operator.add, a, b))
ironfroggy
sumber
4
Saya akan mengatakan ini adalah solusi paling pythonic.
Matthew Schinckel
3
Kecuali map () itu semi-deprecated. Lihat artima.com/weblogs/viewpost.jsp?thread=98196 untuk artikel oleh Guido yang menyebutkan bagaimana peta lebih baik ditulis sebagai pemahaman daftar.
Adam Parkin
Ini juga meledak jika a & b tidak berisi jumlah elemen yang sama, atau tidak "dapat ditambahkan" (mis:map(operator.add, (1,2), ("3", "4"))
Adam Parkin
22
tuple([item1 + item2 for item1, item2 in zip(a, b)])akan menjadi setara dengan pemahaman daftar.
Adam Parkin
11
@AdamParkin, pemahaman generator bahkan lebih baik tuple(item1 + item2 for item1, item2 in zip(a, b)).
Cristian Ciupitu
118

Menggunakan semua bawaan ..

tuple(map(sum, zip(a, b)))
Triptych
sumber
2
Tampaknya ini adalah jawaban yang lebih sederhana dan lebih unggul. Mengapa tidak diterima?
Marc Cenedella
15
itu bagus, tapi secara teknis bukan apa yang diminta karena peta mengembalikan daftar, bukan tuple ... jadi:tuple(map(sum,zip(a,b))
Ben
3
Sintaksnya adalah mistik.
anatoly techtonik
2
Manfaat yang satu ini adalah Anda dapat memperluasnya ke:tuple(map(sum,zip(a,b, c))
Andy Hayden
32

Solusi ini tidak memerlukan impor:

tuple(map(lambda x, y: x + y, tuple1, tuple2))
Boaz Shvartzman
sumber
2
Solusi ini juga lebih cepat daripada solusi satu baris tanpa impor lainnya ( map(sum, zip(a, b)))
Air
20

Urutkan gabungan dua jawaban pertama, dengan tweak ke kode ironfroggy sehingga mengembalikan tupel:

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)

Catatan: menggunakan self.__class__bukannya stuplememudahkan subclassing.

Dana
sumber
18
from numpy import *

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

print a + b

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

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

Mike
sumber
7
Ini akan berfungsi, tetapi agak berat untuk mengimpor numpy hanya untuk operasi penambahan sederhana.
11

Pemahaman generator dapat digunakan sebagai pengganti peta. Fungsi peta bawaan tidak usang tetapi kurang dapat dibaca oleh kebanyakan orang daripada pemahaman daftar / generator / dikt, jadi saya merekomendasikan untuk tidak menggunakan fungsi peta secara umum.

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

solusi sederhana tanpa definisi kelas yang mengembalikan tupel

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

Semua solusi generator. Tidak yakin dengan kinerja (itertools cepat, meskipun)

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

Iya. Tapi Anda tidak bisa mendefinisikan ulang tipe bawaan. Anda harus membuat subkelasnya:

kelas MyTuple (tuple):
    def __add __ (diri sendiri, lainnya):
         jika len (self)! = len (other):
             meningkatkan ValueError ("panjang tuple tidak cocok")
         return MyTuple (x + y untuk (x, y) di zip (self, other))
Doug
sumber
tetapi kemudian Anda tidak dapat menggunakan sintaks tupel.
airportyh
3

lebih sederhana dan tanpa menggunakan peta, Anda dapat melakukannya

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

Saat ini saya membuat subkelas kelas "tuple" untuk membebani +, - dan *. Saya merasa itu membuat kode menjadi indah dan menulis kode lebih mudah.

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)
pengguna2012588
sumber
-1

Jika seseorang perlu membuat daftar rata-rata tupel:

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