Python OOP __Add__ матрицы вместе (проблема зацикливания) - PullRequest
2 голосов
/ 16 марта 2011
class Matrix:
  def __init__(self, data):
    self.data = data

  def __repr__(self):
    return repr(self.data)  

  def __add__(self, other):
    data = []

    for j in range(len(self.data)):
        for k in range(len(self.data[0])):
            data.append([self.data[k] + other.data[k]])
        data.append([self.data[j] + other.data[j]])
        data = []

    return Matrix(data)  

x = Matrix([[1,2,3],[2,3,4]])
y = Matrix([[10,10,10],[10,10,10]])
print(x + y,x + x + y)

Мне удалось получить матрицы для добавления для 1 строки на n столбцов, но когда я попытался улучшить ее для всех матриц размером n на n, добавив во второй цикл, я получил эту ошибку.

Traceback (most recent call last):

  line 24, in <module>
    print(x + y,x + x + y)

  line 15, in __add__
    data.append([self.data[k] + other.data[k]])

IndexError: list index out of range

Ответы [ 2 ]

1 голос
/ 16 марта 2011

Как насчет этого:

class Matrix:
  def __init__(self, data):
    self.data = data

  def __repr__(self):
    return repr(self.data)  

  def __add__(self, other):
    data = []

    for j in range(len(self.data)):
        data.append([])
        for k in range(len(self.data[0])):
            data[j].append(self.data[j][k] + other.data[j][k])

    return Matrix(data)
0 голосов
/ 17 марта 2011

В вашем коде есть несколько проблем ... во-первых, это базовая логика алгоритма сложения

data.append([self.data[k] + other.data[k]])

это утверждение весьма подозрительно ... данные представляют собой двумерную матрицу, но здесь вы получаете доступ к ней с помощью одного индекса. Поэтому data[k] - это целая строка, и, используя +, вы объединяете строки (вероятно, не то, что вы хотели, правильно?). Возможно, решение highBandWidth - это то, что вы искали.

Вторая проблема более тонкая и касается утверждения

self.data = data

Это может быть проблемой, поскольку Python использует так называемую "ссылочную семантику". Ваша матрица будет использовать переданный параметр data для содержимого, но не копировать его. Он будет хранить ссылку на тот же объект списка data, который вы передали конструктору. Может быть, это намеренно, но может быть и нет ... это не ясно. Это нормально для вас, что если вы строите две матрицы из одних и тех же данных, а затем изменяете содержимое одного элемента в первом, меняется и содержимое второго? Если это не так, вы должны скопировать элементы data, а не просто назначить элемент data, например, используя

self.data = [row[:] for row in data]

или используя copy.deepcopy из стандартного модуля копирования .

Третья проблема заключается в том, что вы используете только два пробела для отступа. Это не умно ... при работе в python вы должны использовать отступы 4 пробела и никогда не использовать жесткие символы табуляции. Обратите внимание, что я сказал, что делать это (используя два пробела) не умно, не то, что вы не умны, поэтому, пожалуйста, не принимайте это лично (я даже сделал ту же самую глупую ошибку при запуске с python). Если вы действительно хотите отличаться от других, сделайте это, написав замечательное программное обеспечение без ошибок на python, а не просто используя плохой отступ или выбирая плохие имена для функций или переменных. Сосредоточьтесь на более высоком уровне красоты.

Еще одна проблема заключается в том, что (как только вы действительно поймете, почему ваш код не работает), вы должны действительно прочитать о пониманиях списков Python, инструменте, который может значительно упростить ваш код, если его использовать разумно. Ваш код добавления может, например, стать

return Matrix([[a + b for a, b in zip(my_row, other_row)]
               for my_row, other_row in zip(self.data, other.data)])

Для опытных глаз это легче читать, чем ваш оригинальный код (и это также быстрее).

...