Error: 'Matrix' object is not subscriptable - python

I have created a class in python for matrices and want to have different functions that when applied to a matrix object accomplishes a specific goal. The specific function which have an error is a function to add one matrix to another.
class Matrix:
def __init__(self, rows):
self.rows = rows
self.m = len(rows)
self.n = len(rows[0])
def add(self,other):
output = [[0 for x in range(self.m)] for y in range(self.m)]
for i in range(self.m):
for j in range(self.n):
output[i][j] = self[i][j] + other[i][j]
returnmatrix = Matrix(output)
return returnmatrix
B = Matrix([[1,2,3], [4,5,6], [7,8,9]])
F = Matrix([[1,2,3], [4,5,6], [7,8,9]])
B.add(F)
I expect the output to be a 3x3 matrix that is the addition of matrices B and F. Error recieved is: TypeError: 'Matrix' object is not subscriptable.

The error comes from this line;
for j in range(self.n):
output[i][j] = self[i][j] + other[i][j]
You are subscripting the object but presumably need to be subscripting the rows attribute:
for j in range(self.n):
output.rows[i][j] = self.rows[i][j] + other.rows[i][j]
Also for this to work you need to create output as an instance of Matrix before this, so the full function would be:
def add(self,other):
output = Matrix([[0 for x in range(self.m)] for y in range(self.m)])
for i in range(self.m):
for j in range(self.n):
output.rows[i][j] = self.rows[i][j] + other.rows[i][j]
return output
Also as an aside if you are creating methods like add you should look into dunder methods (e.g. __add__); which will give you the nice functionality of being able to use the plus symbol to add instances of your object together.

Related

Swapping columns of a matrix without numpy

I need to swap the columns of a given matrix by applying some function to (M,i,j) to swap the ith and jth columns of M.
def swap_columns(M,i,j)
rows = M[i]
col = M[i][j]
for i in M:
N = M[i][j]
M[i][j] = M[j][i]
M[j][i] = N
return N
Unable to get this working at all.
In python variable swapping can be done by: x, y = y, x
Code:
This function will modify the original matrix. No need to return
def col_swapper(matrix, col_1, col_2):
for line in range(len(matrix)):
matrix[line][col_1], matrix[line][col_2] = matrix[line][col_2], matrix[line][col_1]
You could do it (in-place) using a for-loop to perform the swapping through unpacking of the matrix's rows:
def swapCols(M,c1,c2):
for row,row[c2],row[c1] in ((row,row[c1],row[c2]) for row in M):pass
you can use this function:
import copy
def my_swap(M, i, j):
temp = copy.deepcopy(M)
for k in range(len(M)):
temp[k][i] = M[k][j]
temp[k][j] = M[k][i]
return temp

Is it possible to use slice in Python in list of complex objects with field of the object

I am new in Python and using python3.
I have list og objects of type points
class Po:
def __init__(self, x: int, y: int):
self.x = x
self.y = y
C = [Po(0, j) for j in range(10)]
and 2 dimensional array
m = [[j for i in range(2)] for j in range(10)]
I want to assign all fields x of C to values with index 0 from m like
C[:].x = m[:][0]
but python says list doesn't have field x.
how can I do this and why I can' access x this way
There's no specific syntax for this in Python. You'll just need to use a regular for loop.
for ci, mi in zip(C, m):
ci.x = mi[0]
Your "C" instance is itself a list, so in order to access it's x or y values, you need to call the index first. So this way you can access them:
for i in range(10):
print(C[i].x)
print(C[i].y)

Matrices Class Calculator Python

In making the function to multiply the matrices my code only prints the first value of the first matrix and fills in all other position with zero. Below is the class with different functions and the multiply matrices function below it. The exception handling works and the printing function works as well. The only problem arises with
class Matrix(object):
"""Input the dimensions of your matrix"""
def __init__(self, rows = 3, cols = 3):
self.rows = rows
self.cols = cols
self.rowList = [ [0 * x for x in range(cols)] for count in range(rows)]
def setRow(self, index = 0, RowData = [0]*2):
"""Enter the index of the row you are defining followed by a string with the values seperated by commas"""
i = 0
if index >= self.cols:
print("Index is out of the bounds that you defined earlier")
return None
if len(RowData) != self.cols:
print("The Row length exceeds the column size of this matrix")
return None
else:
self.rowList[index] = RowData
def rowCount(self):
return self.rows
def columnCount(self):
return self.cols
def get(self, row, col):
return self.rowList[row][col]
def set(self, value = 0, row = 0, col = 0):
self.rowList[row][col] = value
return None
def MultiplyMatrices(A = Matrix(), B = Matrix()):
ARows = A.rowCount()
ACols = A.columnCount()
BRows = B.rowCount()
BCols = B.columnCount()
if ACols != BRows:
print("Matrices are incompatible, therefore cannot be multiplied")
return None
Result = Matrix(ARows, BCols)
for A_row in range(ARows):
for B_col in range(BCols):
Res = 0
for B_row in range(BRows):
Res = Res + A.get(A_row, B_row) * B.get(B_row, B_col)
Result.set(Res, A_row, B_col)
return Result
I think your problem is in your "for" loop.
You have
for B_row in range(BRows):
Res = Res + A.get(A_row, B_row) * B.get(B_row, B_col)
Result.set(Res, A_row, B_col)
return Result
but it should be
for A_row in range(ARows):
for B_col in range(BCols):
Res = 0
for B_row in range(BRows):
Res = Res + A.get(A_row, B_row) * B.get(B_row, B_col)
Result.set(Res, A_row, B_col)
return Result
The way you have things written, your code will return the Result matrix after only calculating the first entry value. I assume you have the other values defaulting to 0, which would explain why the rest of the entries in your Result matrix print as 0.
By the way, one thing you might want to consider is including this Multiply Matrix function in your Matrix class. If you define a class function using this signature
def __mul__(self):
"Your code here"
then when you create two instances of your matrix class, call them A and B, then you can multiply them within your program simply by typing A*B.
You seem to have a two indentation errors so that your MultiplyMatrices won't work correctly. Here's the corrected code:
for A_row in range(ARows):
for B_col in range(BCols):
Res = 0
for B_row in range(BRows):
Res = Res + A.get(A_row, B_row) * B.get(B_row, B_col)
Result.set(Res, A_row, B_col) # this edited so it's the sum over B_row
return Result # this set so it's after all three loops have completed
As a side note, I don't see how your default values (A = Matrix(), B = Matrix()) are ever going to work out well for you. It would almost always be better to just raise an exception if you don't get the needed in input rather than silently returning a matrix of all zeros.
Also, in case you're not already aware, you should know that there's an advanced set of tools for working with matrices in Python called Numpy.

Custom matrix class (using only 1 list), multiplying to matrices

Im trying to create a python class for my assignment. We have to design a custom class handling matrices.
Now Im very new to programming but the main problem I get with this assignment is to multiply two matrices. I can't get my class to actually multiply the rows with more than one column, because I am trying to solve this assignment using only 1 list instead of an array.
I have searched and looked but cant seem to find an answer. I cant use numpy and would like to see if it is doable using just 1 list to describe the matrix.
class simplematrix(object):
def __init__(self,n=0,m=0,values=list()):
self.matrix = []
for x in values:
self.matrix.append(x)
if self.matrix == []:
while len(self.matrix)<n*m:
self.matrix.append(0)
if n*m != len(self.matrix):
raise ValueError('Length of values is different from length of matrix')
self.n = n
self.m = m
def __str__(self):
a = ''
if self.matrix == []:
for x in range(self.n):
a += '\n'
for y in range(self.m):
a += ' '+str(0)
else:
for x in range(self.n):
a += '\n'
for y in range(self.m):
a += ' '+str(self.matrix[y+x*self.m])
return a
def __add__(self,other):
if self.n != other.n or self.m != other.m:
raise ValueError('Matrices have different sizes.')
ans_val = []
for x in range(len(self.matrix)):
ans_val.append(self.matrix[x]+other.matrix[x])
ans = simplematrix(self.n,self.m,ans_val)
return ans
def __mul__(self,other):
if self.m != other.n:
raise ValueError('Matrices have incorrect sizes.')
ans = simplematrix(other.n,self.m)#WTF WTF WTF WTF
for y in range(self.m):
a = self.get_row(y)
b = other.get_col(y)
c = 0
for z in range(len(a)):
c += a[z]*b[z]
ans.matrix[y*self.m] = c
I cant seem to figure out how to get any further. This only calculates the first column of the product matrix. I'm not sure how I can get to change the b to mean another column but still maintain a as being the same column, since i still need to use it :S?
Hope its not to awful to look at.
Any ideas on how to solve this?

Can a python list hold a multi-dimentional array as its element?

I am trying to do image processing using python.
I try to create a list which holds numpy.ndarrays.
My code looks like this,
def Minimum_Close(Shade_Corrected_Image, Size):
uint32_Shade_Corrected_Image = pymorph.to_int32(Shade_Corrected_Image)
Angles = []
[Row, Column] = Shade_Corrected_Image.shape
Angles = [i*15 for i in range(12)]
Image_Close = [0 for x in range(len(Angles))]
Image_Closing = numpy.zeros((Row, Column))
for s in range(len(Angles)):
Struct_Element = pymorph.seline(Size, Angles[s])
Image_Closing = pymorph.close(uint32_Shade_Corrected_Image,Struct_Element )
Image_Close[s] = Image_Closing
Min_Close_Image = numpy.zeros(Shade_Corrected_Image.shape)
temp_array = [][]
Temp_Cell = numpy.zeros((Row, Column))
for r in range (1, Row):
for c in range(1,Column):
for Cell in Image_Close:
Temp_Cell = Image_Close[Cell]
temp_array[Cell] = Temp_Cell[r][c]
Min_Close_Image[r][c] = min(temp_array)
Min_Close_Image = Min_Close_Image - Shade_Corrected_Image
return Min_Close_Image
While running this code I'm getting error:
Temp_Cell = Image_Close[Cell]
TypeError: only integer arrays with one element can be converted to an index
How can I make a data structure which holds different multi-dimensional arrays and then traverse through it??
Making a list of arrays is not necessary when you're using numpy.
I suggest rewriting the whole function like this:
def Minimum_Close(shade_corrected_image, size):
uint32_shade_corrected_image = pymorph.to_int32(shade_corrected_image)
angles = np.arange(12) * 15
def pymorph_op(angle):
struct_element = pymorph.seline(size, angle)
return pymorph.close(uint32_shade_corrected_image, struct_element)
image_close = np.dstack(pymorph_op(a) for a in angles)
min_close_image = np.min(image_close, axis=-1) - shade_corrected_image
return min_close_image
I lower cased variable names so that they stop getting highlighted as classes.
What about:
for cnt,Cell in enumerate(Image_Close):
Temp_Cell = Image_Close[cnt]

Categories

Resources