Элементарные операции с кортежами Python, такие как сумма

101

Есть ли способ заставить операции с кортежами в Python работать следующим образом:

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

вместо того:

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

Я знаю , что это работает , как , что , так как __add__и __mul__методы определяются для работы , как это. Значит, единственный способ - переопределить их?

Родриго
источник

Ответы:

138
import operator
tuple(map(operator.add, a, b))
ironfroggy
источник
4
Я бы сказал, что это самое питоническое решение.
Мэтью Шинкель,
3
За исключением того, что map () частично устарел. См. Статью Гвидо на artima.com/weblogs/viewpost.jsp?thread=98196, в которой упоминается, как лучше написать карту в виде списка.
Адам Паркин,
Он также срабатывает, если a и b не содержат одинакового количества элементов или не являются «добавляемыми» (например:map(operator.add, (1,2), ("3", "4"))
Адам Паркин,
24
tuple([item1 + item2 for item1, item2 in zip(a, b)])будет эквивалентом понимания списка.
Адам Паркин,
13
@AdamParkin, понимание генератора еще лучше tuple(item1 + item2 for item1, item2 in zip(a, b)).
Cristian Ciupitu
120

Использование всех встроенных модулей ..

tuple(map(sum, zip(a, b)))
Триптих
источник
2
Это кажется более простым и лучшим ответом. Почему не принято?
Marc Cenedella 01
15
это хорошо, но технически не то, о чем просят, потому что map возвращает список, а не кортеж ... итак:tuple(map(sum,zip(a,b))
Бен
3
Синтаксис мистический.
анатолий техтоник
2
Преимущество этого в том, что вы можете расширить его до:tuple(map(sum,zip(a,b, c))
Энди Хайден
32

Это решение не требует импорта:

tuple(map(lambda x, y: x + y, tuple1, tuple2))
Боаз Шварцман
источник
2
Это решение также быстрее, чем другое однострочное решение без импорта ( map(sum, zip(a, b)))
Air
20

Как бы объединил первые два ответа с изменением кода ironfroggy, чтобы он возвращал кортеж:

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)

Примечание: используйте self.__class__вместо, stupleчтобы облегчить создание подклассов.

Дана
источник
18
from numpy import array

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

print a + b

дает array([4,4,4]).

См. Http://www.scipy.org/Tentative_NumPy_Tutorial

Майк
источник
7
Это будет работать, но импортировать numpy только для простой операции сложения немного сложно.
11

Понимание генератора может использоваться вместо карты. Встроенная функция карты не устарела, но для большинства людей она менее читабельна, чем понимание списка / генератора / словаря, поэтому я бы рекомендовал не использовать функцию карты в целом.

tuple(p+q for p, q in zip(a, b))
Джэхён Ём
источник
6

простое решение без определения класса, которое возвращает кортеж

import operator
tuple(map(operator.add,a,b))
DemonEye
источник
6

Все генераторное решение. Не уверен в производительности (хотя itertools работает быстро)

import itertools
tuple(x+y for x, y in itertools.izip(a,b))
Майк
источник
3

Да. Но вы не можете переопределить встроенные типы. Вы должны разделить их на подклассы:

класс MyTuple (кортеж):
    def __add __ (себя, другое):
         если len (self)! = len (другое):
             поднять ValueError ("длины кортежей не совпадают")
         вернуть MyTuple (x + y для (x, y) в zip (self, other))
Дуг
источник
но тогда вы не можете использовать синтаксис кортежа.
airportyh
3

еще проще и без использования карты, вы можете сделать это

>>> tuple(sum(i) for i in zip((1, 2, 3), (3, 2, 1)))
(4, 4, 4)
LetsPlayYahtzee
источник
1

В настоящее время я создаю подкласс класса «кортеж» для перегрузки +, - и *. Я считаю, что это делает код красивым и упрощает его написание.

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)
пользователь2012588
источник
-1

Если кому-то нужно усреднить список кортежей:

import operator 
from functools import reduce
tuple(reduce(lambda x, y: tuple(map(operator.add, x, y)),list_of_tuples))
ytutow
источник