python class __mul__
обучаюсь на coursera. Сейчас последняя неделя и резко все перешло в ООП. Что было понятнее, 7 недель, объяснили что такое +, что такое -, что такое float. А на последней неделе - резко ООП + конструктор классов. Я честно говоря подсъехал.
Вот пример кода:
from sys import stdin
from copy import deepcopy
class MatrixError(BaseException):
def __init__(self, r1, other):
self.matrix1 = r1
self.matrix2 = other
class Matrix:
def __init__(self, lists):
self.lists = deepcopy(lists)
def __str__(self):
strRep = ""
amount = 0
for lists in self.lists:
if amount != 0:
strRep += "\n"
new_str = "\t".join(str(elem) for elem in lists)
strRep += new_str
amount += 1
return strRep
def size(self):
return len(self.lists), len(self.lists[0])
def __add__(self, other):
if len(self.lists) == len(other.lists):
lenght = len(self.lists[0])
for row in self.lists:
if len(row) != lenght:
raise MatrixError(self, other)
for row2 in other.lists:
if len(row2) != lenght:
raise MatrixError(self, other)
result = []
numbers = []
for i in range(len(self.lists)):
for j in range(len(self.lists[0])):
summa = other.lists[i][j] + self.lists[i][j]
numbers.append(summa)
if len(numbers) == len(self.lists[0]):
result.append(numbers)
numbers = []
return Matrix(result)
else:
raise MatrixError(self, other)
def __mul__(self, alpha):
if isinstance(alpha, Matrix):
result = []
numbers = []
for i in range(len(self.lists)):
for j in range(len(self.lists[0])):
numbers.append(int(alpha * self.lists[i][j]))
if len(numbers) == len(self.lists[0]):
result.append(numbers)
numbers = []
else:
result = []
numbers = []
for i in range(len(self.lists)):
for j in range(len(self.lists[0])):
numbers.append(int(self.lists[i][j] * alpha))
if len(numbers) == len(self.lists[0]):
result.append(numbers)
numbers = []
return Matrix(result)
__rmul__ = __mul__
def transpose(self):
t_matrix = list(zip(*self.lists))
self.lists = t_matrix
return Matrix(t_matrix)
def transposed(self):
t_matrix = list(zip(*self.lists))
return Matrix(t_matrix)
# Task 2 check 3
m = Matrix([[1, 1, 0], [0, 2, 10], [10, 15, 30]])
alpha = 15
print(m * alpha)
print(alpha * m)
#exec(stdin.read())
Он правильно отрабатывает последние выражения(при этом вывод соответствует требованиям coursera). Но, ругается и не пропускает. Пишет - runtime error. Как правило, такая ошибка возникает из-за косяков в цикле. Пробовал убрать проверку
if instanse(alpha, Matrix)
-не помогло. Я их не вижу в упор. ну предельно же просто.
На всякий случай, прошедшие тесты:
Тест 1
Входные данные:
# Task 2 check 1
m = Matrix([[10, 10], [0, 0], [1, 1]])
print(m.size())
Вывод программы:
(3, 2)
Тест 2
Входные данные:
# Task 2 check 2
m1 = Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
m2 = Matrix([[0, 1, 0], [20, 0, -1], [-1, -2, 0]])
print(m1 + m2)
Вывод программы:
1 1 0
20 1 -1
-1 -2 1
Ответы (1 шт):
Неправильно умножаете матрицу на матрицу. Посмотрите на ютубе урок на эту тему. У вас вообще одинаковый код для умножения матрицы на число и матрицы на матрицу.
Я решил вашу задачу по своему, постаравшись написать pytonic код (с использованием фич языка) с минимумом дублирования в ущерб производительности.
Проверки и обработки ошибок не стал добавлять, чтобы не загромождать решение, только суть. Как минимум надо добавить проверки соответствия размеров матриц: для сложения и вычитания матрицы должны быть одинакового размера, для умножения количество столбцов матрицы m должно совпадать с количеством строк матрицы n. Если что-то непонятно, спрашивайте.
import operator
class Matrix:
def __init__(self, lst):
self.lst = lst
def __str__(self):
lst_of_strs = ['\t'.join(map(str, row)) for row in self.lst]
return '\n'.join(lst_of_strs)
def size(self):
return len(self.lst), len(self.lst[0])
def operation_on_pairs(self, operand_2, op):
if self.size() == operand_2.size():
return [[op(a, b) for a, b in zip(row_1, row_2)] for row_1, row_2 in zip(self.lst, operand_2.lst)]
def __add__(self, operand_2):
return Matrix(self.operation_on_pairs(operand_2, operator.add))
def __sub__(self, operand_2):
return Matrix(self.operation_on_pairs(operand_2, operator.sub))
def __mul__(self, operand_2):
def mul(row, col):
return sum(a * b for a, b in zip(row, col))
res_mtrx = Matrix([])
for row in self.lst:
if isinstance(operand_2, int):
res_mtrx.lst.append([col * operand_2 for col in row])
else:
res_mtrx.lst.append([mul(row, col) for col in zip(*operand_2.lst)])
return res_mtrx
__rmul__ = __mul__
def _transpose(self):
return list(zip(*self.lst))
def transpose(self):
self.lst = self._transpose()
def transposed(self):
return Matrix(self._transpose())
Тестирование
m = [
[1, 1, 0],
[0, 2, 10],
[10, 15, 30]
]
n = [
[2, 1, 2],
[3, 2, 5],
[10, 15, 30]
]
m = Matrix(m)
n = Matrix(n)
print("{:#^50}".format("Оригинальные матрицы m и n"))
print(m, end="\n\n")
print(n, end="\n\n")
print("{:#^50}".format("Результат умножения матриц m и n"))
print(m * n, end="\n\n")
print("{:#^50}".format("Результат сложения матриц m и n"))
print(m + n, end="\n\n")
print("{:#^50}".format("Транспонированная матрица m"))
print(m.transposed(), end="\n\n")
Output
############Оригинальные матрицы m и n############
1 1 0
0 2 10
10 15 30
2 1 2
3 2 5
10 15 30
#########Результат умножения матриц m и n#########
5 3 7
106 154 310
365 490 995
#########Результат сложения матриц m и n##########
3 2 2
3 4 15
20 30 60
###########Транспонированная матрица m############
1 0 10
1 2 15
0 10 30