2015-09-06 2 views
4

Я пытаюсь создать метод (сумму), который принимает переменное число векторов и добавляет их. Для образовательных целей я написал собственный класс Vector, а базовые данные - хранится в переменной экземпляра с именем data.Pythonic способ добавить список векторов

Мой код для @classmethod сумма работает (для каждого из векторов, прошедших через, перебирает каждый элемент в переменной данных и добавляет его в список результатов), но кажется не-питоническим, и задается вопросом, существует ли лучший путь?

class Vector(object): 
    def __init__(self, data): 
     self.data = data 

    @classmethod 
    def sum(cls, *args): 
     result = [0 for _ in range(len(args[0].data))] 
     for v in args: 
      if len(v.data) != len(result): raise 
      for i, element in enumerate(v.data): 
       result[i] += element 

     return cls(result) 
+2

http://codereview.stackexchange.com –

+0

Почему метод класса? – msw

+0

Я думал, что сумма должна вернуть новый вектор и, таким образом, использовать метод класса. –

ответ

6

itertools.izip_longest может прийти очень удобно в вашей ситуации:

a = [1, 2, 3, 4] 
b = [1, 2, 3, 4, 5, 6] 
c = [1, 2] 

lists = (a, b, c) 

result = [sum(el) for el in itertools.izip_longest(*lists, fillvalue=0)] 

А вот вы получили то, что хотели:

>>> result 
[3, 6, 6, 8, 5, 6] 

Что она делает это просто застегивает свои списки вместе, заполняя пустое значение с 0. например izip_longest(a, b) будет [(1, 1), (2, 2), (3, 0), (4, 0)]. Затем просто суммируйте все значения в каждом элементе набора промежуточного списка.

Итак, вы идете шаг за шагом:

>>> lists 
([1, 2, 3, 4], [1, 2, 3, 4, 5, 6], [1, 2]) 
>>> list(itertools.izip_longest(*lists, fillvalue=0)) 
[(1, 1, 1), (2, 2, 2), (3, 3, 0), (4, 4, 0), (0, 5, 0), (0, 6, 0)] 

Так что, если вы бежите список понимание, суммируя все вложенные элементы, вы получите результат.

+0

Спасибо, и это работает! –

2
args = [[1, 2, 3], 
     [10, 20, 30], 
     [7, 3, 15]] 

result = [sum(data) for data in zip(*args)] 
# [18, 25, 48] 

Является ли это то, что вы хотите?

5

Другая вещь, которую вы могли бы сделать (и это могло бы быть более «pythonic»), было бы реализовать __add__ magic method, поэтому вы можете использовать + и sum прямо на векторах.

class Vector(object): 
    def __init__(self, data): 
     self.data = data 

    def __add__(self, other): 
     if isinstance(other, Vector): 
      return Vector([s + o for s, o in zip(self.data, other.data)]) 
     if isinstance(other, int): 
      return Vector([s + other for s in self.data]) 
     raise TypeError("can not add %s to vector" % other) 

    def __radd__(self, other): 
     return self.__add__(other) 

    def __repr__(self): 
     return "Vector(%r)" % self.data 

Здесь я также осуществил добавление Vector и int, добавив число на каждом из элементов данных вектора, и «обратного дополнения» __radd__, чтобы sum работать должным образом.

Пример:

>>> v1 = Vector([1,2,3]) 
>>> v2 = Vector([4,5,6]) 
>>> v3 = Vector([7,8,9]) 
>>> v1 + v2 + v3 
Vector([12, 15, 18]) 
>>> sum([v1,v2,v3]) 
Vector([12, 15, 18]) 
+0

Спасибо за это, и я не рассматривал этот подход и узнал что-то новое! –

Смежные вопросы