Error of argument in method of matrix class - Python - python

I create matrix class in python 3 (so far I have only create one method):
class Matrix() :
__rows = []
__columns = []
def SetRows(self,rows) :
self.__rows = rows
i = 0
while i < len(rows[0]) :
a = []
j = 0
while j < len(rows) :
a.append(rows[j][i])
j += 1
self.__columns.append(a)
i += 1
m = Matrix
m.SetRows([[0,8,56],[98,568,89]])
But it gives this error:
Traceback (most recent call last):
File "f:\PARSA\Programming\Python\2-11-2.py", line 14, in <module>
m.SetRows([[0,8,56],[98,568,89]])
TypeError: SetRows() missing 1 required positional argument: 'rows'
I've entered 'rows' argument. Obviously, I don't need to enter 'self'. I use VS Code for IDE. Thanks for your help.

Everything's fine with your function.
You just forgot the brackets when instantiating m=Matrix(). So the interpreter thinks you have to specify self, since it didn't recognize the class.
EDIT:
I've just recognized another problem. You actually created an infinite loop with those while loops. If you don't addition-assign i and j those will always stay below len(rows[0]) and len(rows) respectively.
So:
class Matrix() :
__rows = []
self.__columns = []
def SetRows(self,rows) :
self.__rows = rows
i = 0
while i < len(rows[0]) :
a = []
j = 0
while j < len(rows) :
a.append(rows[j][i])
j += 1
self.__columns.append(a)
i += 1
m = Matrix()
m.SetRows([[0,8,56],[98,568,89]])

Related

I want to print a Matrix in an specific format using the __str__ method [duplicate]

This question already has answers here:
How can I use `return` to get back multiple values from a loop? Can I put them in a list?
(2 answers)
Why does the print function return None?
(1 answer)
Can I return several lines using __str__?
(2 answers)
Closed 6 months ago.
I wanna print an all zeros matrix this way:
0 0 0
0 0 0
0 0 0
In order to do that i gotta use the __str__ method. This is what I've gotten so far:
class Matrix:
def __init__(self, m, n):
self.rows = m # rows
self.cols = n # columns
self.matrix = [] # creates an array
for i in range(self.rows):
self.matrix.append([0 for i in range(self.cols)])
def __str__(self):
# string = ""
for element in self.matrix:
return print(*element)
a_matrix = Matrix(3, 3)
print(a_matrix)
But when i run the code, there's an error:
Traceback (most recent call last):
File "C:\Users\DELL USER\Google Drive\Programacion\Negocios\main.py", line 72, in <module>
print(a_matrix)
TypeError: __str__ returned non-string (type NoneType)
0 0 0
Process finished with exit code 1
Note how i'm using return print(*element), usually, out of the str method it works just fine but when i use it that way, it stops working. Is there a way i can covert that print to a string so i can get rid of the error?
def __str__(self): needs to return a string. You can do this:
class Matrix:
def __init__(self, n, m):
self.matrix = []
for i in range(n):
self.matrix.append([0 for i in range(m)])
def __str__(self):
outStr = ""
for i in range(len(self.matrix)):
for c in self.matrix[i]:
outStr += str(c)
outStr += "\n"
return outStr
matrix = Matrix(3, 3)
print(matrix)
a_matrix has a property "matrix" print that?
class Matrix:
def __init__(self, m, n):
self.rows = m # rows
self.cols = n # columns
self.matrix = [] # creates an array
for i in range(self.rows):
self.matrix.append([0 for i in range(self.cols)])
def __str__(self):
# string = ""
for element in self.matrix:
return print(*element)
a_matrix = Matrix(3, 3)
for i in range(a_matrix.rows):
for j in range(a_matrix.cols):
print(a_matrix.matrix[i][j], end = " ")
print()

How can I assign zero to missing variable in function

First of all, thank you for reading it. I am new to Python and learning something new every day.
I wrote a function where inputs are 4 variables and output are 4 variables.
My problem is variables are getting defined somewhere else and it's calling the script. Now, what if the user only defines 3 variables in that case I automatically want a 4th variable to get assigned zero value. I also included another code that I am trying to use for the same purpose.
volsum = vol1 + vol2 + vol3 + vol4
if vol1n == missing:
vol1n = 0
else:
vol1n=vol1/volsum
if vol2n == missing:
vol2n = 0
else:
vol2n=vol2/volsum
if vol3n = missing:
vol3n = 0
else:
vol3n=vol3/volsum
if vol4n == missing:
vol4n = 0
else:
vol4n=vol4/volsum
or maybe using a function
def vol(vol1,vol2,vol3,vol4):
volsum = vol1 + vol2
vol1n=vol1/volsum
vol2n=vol2/volsum
vol3n=vol3/volsum
vol4n=vol4/volsum
return vol1n, vol2n,vol3n,vol4n
Try Assigning Values when you Define the Fucntion:
def vol(vol1 = 0,vol2 = 0,vol3 = 0,vol4 = 0):
volsum = vol1 + vol2
vol1n = vol1 / volsum
vol2n = vol2 / volsum
vol3n = vol3 / volsum
vol4n = vol4 / volsum
return vol1n, vol2n,vol3n,vol4n
Now suppose you want to skip vol2:
variable_assigned = vol(vol1 = 5,vol3 = 2,vol4 = 5)
If you require a One-Line (I love creating one):
#defining vol()
def vol(*kwargs): return [i/sum(kwargs) for i in kwargs]
# using vol()
#example
vol (1,2,3)
#returns
[0.16666666666666666, 0.3333333333333333, 0.5]
# so to assign variables,
#if you give 3 values,
vol1n, vol2n, vol3n = vol(1,2,3)
# if 4,
vol1n, vol2n, vol3n, vol4n = vol(1,2,3,5)
A little Fun (Not recommended):
Lets say your vol1 =1, vol2 = 5 vol3 = 3 ...voln = 10
So let:
vol = [ 1, 5, 3, ... n values, 10]
Now if you run the following code:
for j in range(len(vol)): exec(f'vol{j+1}n = [i/sum(vol) for i in vol][j]')
This code will automatically create your vol1n, vol2n, ... volnn variables automatically.
Rather than a 0, could it be forgotten? Personally, I don't like typing things out when they don't need to be. Try the *args feature out.
def vol_func(*args):
volumesum = sum(args)
vals = []
for i in range(len(args)):
vals.append(args[i] / volumesum)
return vals
volsumlst = vol_func(2.3, 4)
You can check if a variable is defined or not using 'locals' function. Alternatively if variables are defined globally, then you should use 'globals' function.
if 'vol1n' not in locals():
vol1n = 0
else:
vol1n=vol1/volsum
if 'vol2n' not in locals():
vol2n = 0
else:
vol2n=vol2/volsum
if 'vol3n' not in locals():
vol3n = 0
else:
vol3n=vol3/volsum
if 'vol4n' not in locals():
vol4n = 0
else:
vol4n=vol4/volsum

How is __setitem__() working with 4 arguments?

I'm writing a Matrix class with the [] operator overloaded.
Since my self.matrix which holds the matrix is a list of lists, the __getitem__() method as per convention takes 2 parameters self, index, returns a list(row) which can further be subscripted.
But what about __setitem__()? Isn't it supposed to take only 3 parameters by definition? I have tried it with 4 parameters and it is somehow working fine.
I know a tuple argument can be passed in to access the matrix elements but I would like to know why is this working with 4 parameters? Is this undefined behavior? If I write m_obj[rindex][cindex] = val, it works flawlessly!
Also if I just do m_obj[rindex] = val, I get the following error:
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
a[1] = 1
TypeError: __setitem__() missing 1 required positional argument: 'val'
But this indeed is what I want except the positional argument missing was cindex not val.
On the contrary, if I add an additional parameter to __getitem__(), the code doesn't work :
def __getitem__(self, rindex, cindex):
return self.matrix[rindex][cindex]
And I get this error both while getting and setting:
>>> a[1][1] = 1
Traceback (most recent call last):
File "<pyshell#21>", line 1, in <module>
a[1][1] = 1
TypeError: __getitem__() missing 1 required positional argument: 'cindex'
Here's the code:
class DimensionError(BaseException):
pass
class Matrix:
def __init__(self, rows, cols):
self.rows = rows
self.cols = cols
self.matrix = [[] for i in range(self.rows)]
for i in range(self.rows):
self.matrix.app
for j in range(self.cols):
self.matrix[i].append(0)
def __str__(self):
matrep = ''
for i in self.matrix:
matrep += str(i) + '\n'
return matrep
def __getitem__(self, index):
return self.matrix[index]
def __setitem__(self, rindex, cindex, val):
self.matrix[rindex][cindex] = val
def __add__(self, secmat):
if self.rows != secmat.rows or self.cols != secmat.cols:
raise DimensionError('Incompatible Matrices for Addition')
newmat = Matrix(self.rows, self.cols)
for i in range(self.rows):
for j in range(self.cols):
newmat[i][j] = self[i][j] + secmat[i][j]
return newmat
def __sub__(self, secmat):
if self.rows != secmat.rows or self.cols != secmat.cols:
raise DimensionError('Incompatible Matrices for Subtraction')
newmat = Matrix(self.rows, self.cols)
for i in range(self.rows):
for j in range(self.cols):
newmat[i][j] = self[i][j] - secmat[i][j]
return newmat
def __matmul__(self, secmat):
if self.cols != secmat.rows:
raise DimensionError('Incomatible Matrices for Multiplication. Product is undefined')
newmat = Matrix(self.rows, secmat.cols)
for i in range(self.rows):
for j in range(secmat.cols):
for k in range(secmat.rows):
newmat[i][j] += (self[i][k] * self[k][j])
return newmat
def __mul__(self, secmat):
return self.__matmul__(secmat)
#Driver
a = Matrix(2, 2)
b = Matrix(2, 2)
print('Enter elements of first matrix:')
for i in range(a.rows):
for j in range(a.cols):
a[i][j] = int(input(f'Enter element [{i}{j}] >>>'))
print('Enter elements of second matrix:')
for i in range(b.rows):
for j in range(b.cols):
b[i][j] = int(input(f'Enter element [{i}{j}] >>>'))
print('Matrix a: ')
print(a)
print('Matrix b: ')
print(b)
print('Multiplication is:')
print(a # b) # or a * b
I have tried it in Python 2.7 without f-strings and # operator and it works just the same .
Can someone explain what is going on under the hood?
Thanks in Advance!
It isn't working. It isn't being called at all.
When you do m_obj[rindex][cindex] = val, Python calls __getitem__ to get the value of m_obj[rindex]. Then it will call the __setitem__ method of whatever that value is. You can prove this to yourself by putting a print within your method.

nested if for variable names with pattern

Recently I wrote a program as follows:
empty_list = []
for row in rows:
if row.num1 != 0:
empty_list.extend(row.amt1)
if row.num2 != 0:
empty_list.extend(row.amt2)
if row.num3 != 0:
empty_list.extend(row.amt3)
if row.num4 != 0:
empty_list.extend(row.amt4)
this pattern goes on till num10.
Basically we are extending the list till we find row.num{d} = 0.
My question is since the variables are numbered, can we do something in a pythonic way or in a loop.
The example is simplified. We are importing legacy data from an old dbase format.
I'm guessing the class structure of a row is like this.
# This is a mock class
class Row:
def __init__(self):
self.num1 = 32
self.num2 = 23
self.num3 = 323
self.num4 = 213
self.num5 = 23
self.num6 = 0
self.amt1 = [20]
self.amt2 = [320]
self.amt3 = [320]
self.amt4 = [340]
self.amt5 = [30]
self.amt6 = [330]
Then you can use getattr like this
row = Row()
empty_list = []
i = 1
while (getattr(row, "num{}".format(i)) != 0):
empty_list.extend(getattr(row, "amt{}".format(i)))
i += 1
import itertools
import contextlib
for row in rows:
with contextlib.supress(AttributeError):
for i in itertools.count(start=1):
if getattr(row, f'num{i}') != 0:
empty_list.extend(getattr(row, f'amt{i}'))
break
should work. For each row, getattr is used until AttributeError is raised and next row is processed.
Note: the above code uses f-strings, so you need python 3.6+ to use them. If you use an older version, simply use .format().
You can try to use eval() function
empty_list = []
for row in rows:
for i in range(1, 11):
if eval('row.num' + str(i)) != 0:
empty_list.extend(eval('row.atm' + str(i)))

Python "object() takes no parameters" error

I'm having this problem when I clearly use init function to declare the parameters. Link my code there:
class Node:
def _init_(self,pieza,turno,listaAsignados,parent,costeCamino,coste):#Initialize a Node
self.pieza = pieza
self.turno = turno
self.listaAsignados = listaAsignados
self.parent = parent
self.costeCamino = costeCamino
self.costeNodo = costeNodo
def calculateCost(C, i, j, listaPadre,M): #Calculate Cost of the next element
initCost = 0
cost = 0
listaDisponibles = [1]*M
for i in range(i,M-1):
minNum = 9999999999
minIndex = -1
for j in range(j,M-1):
if(not listaPadre[j] and listaDisponibles[j] and C[i][j]< minNum ):
minIndex = j
minNumber = costMatrix[i][j]
cost = cost+ minNumber
return cost
import heapq
def branch_bound(C):
"""
-C = Matrix of costs
"""
items=[]
priorityQueue = []
heapq.heapify(priorityQueue)
listaAsignados = [0]*M#Asigned list for the matrix
raiz = Node(-1,-1,listaAsignados,None,0,0)
heapq.heappush(listaAsignados,[raiz.cost,raiz])
while (priorityQueue):
examinateNode = heapq.heappop(priorityQueue)
examinateNode = examinateNode[1]
i = examinateNode.pieza+1
if (i == M):
return examinateNode.cost
for j in range(0,M-1):
if(examinateNode.listaAsignados[j] == 0):
costeCamino = examinateNode.pathCost+ C[i][j]
costeHijo = costeCamino+ calculateCost(C, i, j, examinateNode.listaAsignados,M)
nodoHijo = Node(i,j,examinateNode.listaAsignados,examinateNode,costeCamino,costeHijo)
heapq.heappush(listaAsignados,[nodoHijo.cost,nodoHijo])
return items
If someone can explain me why this error is going on I will appreciate it. I don't know why if I have a constructor the error is going on:
<ipython-input-10-8d5dfd71f776> in branch_bound(C)
11 heapq.heapify(priorityQueue)
12 listaAsignados = [0]*M
13 raiz = Node(-1,-1,listaAsignados,None,0,0)<-------
14 heapq.heappush(listaAsignados,[raiz.cost,raiz])
15
TypeError: object() takes no parameters
You need to write __init__ instead of _init_.

Categories

Resources