Элементарные операции с кортежами 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))

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))

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)

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)

-1

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

import operator 
from functools import reduce
tuple(reduce(lambda x, y: tuple(map(operator.add, x, y)),list_of_tuples))
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.