python cast object to int - python

I am using the numpy module to retrieve the position of the maximum value in a 2d array. But this 2d array consists of MyObjects. Now I get the error:
TypeError: unorderable types: int() > MyObject()
I tried to override the int function with this code:
def int(self):
return self.score
But this does not solve my problem.
Do I have to convert my 2d array of MyObjects into a 2d array of integers, do I have to extend the Integer object (if this is possible in python) or can I override this int() function in another way?
[EDIT]
The full object:
class MyObject:
def __init__(self, x, y, score, direction, match):
self.x = x
self.y = y
self.score = score
self.direction = direction
self.match = match
def __str__(self):
return str(self.score)
def int(self):
return self.score
The way I call this object:
def traceBack(self):
self.matrix = np.array(self.matrix)
maxIndex = self.matrix.argmax()
print(self.matrix.unravel_index(maxIndex))

Try to use
...
def __int__(self):
return self.score
...
test = MyObject(0, 0, 10, 0, 0)
print 10+int(test)
# Will output: 20
in your MyObject class definition.

The max function takes a key that is applied on the elements. that's where you put score
Typically :
a = max(my_list, key=score)

Related

Add function not working - what I want is to be able to sum two matrices

I want to sum two matrices, so I'm doing the __add__ method, but it doesn’t seem to work. Can somebody help me please? I don’t know what I'm doing wrong. This is my code:
class Matrix():
def __init__(self, width = int, height = int, fill_value=0):
self.height = height #columna
self. width = width #fila
self.rows = [[fill_value] * width for _ in range (height)] #A for matrix A
def __str__(self):
return "\n" .join(" ".join(map(str, self.rows))for self.rows in self.rows)
def set(self, row_index = int, column_index = int, value = int):
self.rows[row_index][column_index] = value
def get(self, row_index, column_index):
return self.rows[row_index][column_index]
def __add__(self, other):
matrix_addition = []
for i in range(self.height):
new_row = []
for j in range(self.width):
addition = self.rows[i][j] + other.rows[i][j]
new_row.append(addition)
matrix_addition.append(new_row)
return Matrix(matrix_addition)
I'm having an error that says:
addition = self.rows[i][j] + other.rows[i][j],
TypeError : ‘int’ object has no attribute ‘__getitem__’
Your code is pretty good, you almost got it.
The first issue is your constructor and the set() method: by using
the default value=int in the parameters, you're essentially assigning type(int), which is not what you want. You should either assign a default value, say 2 or use type hinting to specify data type, say int. Here's an example with both type hinting and defaults:
def __init__(self, width: int = 2, height: int = 2, fill_value=0):
pass
def set(self, row_index: int, column_index: int, value: int):
pass
Here is the fatal error in your __add__ method: return Matrix(matrix_addition). This creates a new Matrix object and passes matrix_addition as an argument. However, the first argument in Matrix.__init__ is width, which expects an int, not List[List[int]]. Instead, call return matrix_addition and it will work.

Storing and checking a boolean in a python class

So I was trying to create an object which basically has a constructor that takes two coordinates, xcoord and ycoord. I further created methods which shift the coordinates and I have to check if the point is valid or not(criteria for validity is if the coordinates are out of a specified range it should return False else True).
Problem:
My class only returns the validity for the initial points, not the shifted points.
What do I need to correct my code?
Code:
class Point:
MaxScreenSize=10
def __init__(self,x,y):
self.xcoord=x
self.ycoord=y
if 0>self.xcoord or self.xcoord>Point.MaxScreenSize or 0>self.ycoord or self.ycoord>Point.MaxScreenSize:
Point.isValidPt=False
else:
Point.isValidPt=True
def translateX(self,shiftX):
self.xcoord=self.xcoord+shiftX
def translateY(self,shiftY):
self.ycoord=self.ycoord+shiftY
Test Code:
I tried my code and it only returns the isValidFunction variable for my initial points (gives me True instead of False for following code)
p=Point(9,2)
p.translateX(20)
p.translateY(10)
p.isValidPt
Your isValidPt is only calculated when the class is instantiated. Instead try something like:
Code:
class Point:
MaxScreenSize = 10
def __init__(self, x, y):
self.xcoord = x
self.ycoord = y
def translateX(self, shiftX):
self.xcoord = self.xcoord + shiftX
def translateY(self, shiftY):
self.ycoord = self.ycoord + shiftY
#property
def isValidPt(self):
return (
0 <= self.xcoord <= Point.MaxScreenSize and
0 <= self.ycoord <= Point.MaxScreenSize
)
Test Code:
p = Point(9, 2)
p.translateX(20)
p.translateY(10)
print(p.isValidPt)
Result:
False
Constructor is used basically for initiate the values. In your case the constructor checks the initial value and set the validate flag. ie, isValidPt.
It will be True for the scope of p object you created. So you have to create a validate function and call the validate function on both init and shift functions.
Check the following
class Point:
MaxScreenSize=10
def __init__(self,x,y):
self.xcoord=x
self.ycoord=y
self.validate()
def validate(self):
if 0>self.xcoord or self.xcoord>Point.MaxScreenSize or 0>self.ycoord or self.ycoord>Point.MaxScreenSize:
Point.isValidPt=False
else:
Point.isValidPt=True
def translateX(self,shiftX):
self.xcoord=self.xcoord+shiftX
self.validate()
def translateY(self,shiftY):
self.ycoord=self.ycoord+shiftY
self.validate()
in the above code each time the validation will perform and update the values
of isValidPt.

How to call method of other object in Python?

I am new in python, and I have small problem, I have two classes, and it wrotes this : set_gyro_angle() takes exactly 1 argument (2 given) how can I call set_gyro_angle() method from Machine method?
class Gyro(object):
"""gyroskop senzor"""
def __init__(self,gyro_start_angle = 0):
self.gyro_angle = 0
def get_gyro_angle():
return self.gyro_angle
def set_gyro_angle(angle):
self.gyro_angle = angle
return 0
class Maschine(object):
def __init__(self, state = "normal",length = 10,width = 15):
self.length = length
self.width = width
self.gyro = Gyro()
def setPoint(self,alpha):
self.gyro.set_gyro_angle(alpha)
return 0
Main:
maschine = Maschine()
maschine.setPoint()
If you want to create an instance method, you need to add an extra argument that will be a pointer to your instance. Usually it's self:
class Gyro(object):
"""gyroskop senzor"""
def __init__(self,gyro_start_angle = 0):
self.gyro_angle = 0
def get_gyro_angle(self):
return self.gyro_angle
def set_gyro_angle(self, angle):
self.gyro_angle = angle
return 0
And i think you want setPoint to be like this:
def setPoint(self, alpha):
self.gyro.set_gyro_angle(alpha)
All of your instance methods should have another parameter, self, before the others; this is the instance itself, and is passed automatically:
def set_gyro_angle(self, angle):
Alternatively, skip the setter:
self.gyro.gyro_angle = alpha
Machine.gyro.set_gyro_angle(45)
However you need to fix your code by adding the self parameter as the first parameter of your class methods.

line 60, in make_tuple return tuple(l) TypeError: iter() returned non-iterator of type 'Vector'

I am new to Vectors and making classes. I am trying to construct my own vector class but when i pass it through my code which is:
position += heading*distance_moved
where position and heading are both vectors. heading is normalized. my goal is to repeat my code until position = destination.
What is wrong with this class?
import math
class Vector(object):
#defaults are set at 0.0 for x and y
def __init__(self, x=0.0, y=0.0):
self.x = x
self.y = y
#allows us to return a string for print
def __str__(self):
return "(%s, %s)"%(self.x, self.y)
# from_points generates a vector between 2 pairs of (x,y) coordinates
#classmethod
def from_points(cls, P1, P2):
return cls(P2[0] - P1[0], P2[1] - P1[1])
#calculate magnitude(distance of the line from points a to points b
def get_magnitude(self):
return math.sqrt(self.x**2+self.y**2)
#normalizes the vector (divides it by a magnitude and finds the direction)
def normalize(self):
magnitude = self.get_magnitude()
self.x/= magnitude
self.y/= magnitude
#adds two vectors and returns the results(a new line from start of line ab to end of line bc)
def __add__(self, rhs):
return Vector(self.x +rhs.x, self.y+rhs.y)
#subtracts two vectors
def __sub__(self, rhs):
return Vector(self.x - rhs.x, self.y-rhs.y)
#negates or returns a vector back in the opposite direction
def __neg__(self):
return Vector(-self.x, -self.y)
#multiply the vector (scales its size) multiplying by negative reverses the direction
def __mul__(self, scalar):
return Vector(self.x*scalar, self.y*scalar)
#divides the vector (scales its size down)
def __div__(self, scalar):
return Vector(self.x/scalar, self.y/scalar)
#iterator
def __iter__(self):
return self
#next
def next(self):
self.current += 1
return self.current - 1
#turns a list into a tuple
def make_tuple(l):
return tuple(l)
I guess you are using python 3.x, because I've got a similar error.
I'm also new on making class, but it would be nice to share what I learned :)
In 3.x, use __next__() instead of next() in the definition of classes.
The error haven't occurred after I renamed it in your code, but I got another problem, "'Vector' object has no attribute 'current'" :)
I think it might be better for you to understand iterators (and class?) more.
A simplest example is:
class Count:
def __init__(self, n):
self.max = n
def __iter__(self):
self.count = 0
return self
def __next__(self):
if self.count == self.max:
raise StopIteration
self.count += 1
return self.count - 1
if __name__ == '__main__':
c = Count(4)
for i in c:
print(i, end = ',')
and the outputs are 0,1,2,3,.
With a vector class, I want to iterate the components of the vector. So:
def __iter__(self):
self.count = 0
self.list = [self.x, self.y, self.z] # for three dimension
return self
def __next__(self):
if self.count == len(self.list):
raise StopIteration
self.count += 1
return self.list[self.count - 1]
and the iterator outputs the sequence x, y, z.
Note that the most important feature of iterators is to give the sequence step by step without creating whole list. So it is not very good idea to make self.list if the sequence will be very long.
More details here: python tutorial
The first argument that's being passed into make_tuple is your Vector instance (it's the same self argument that you put everywhere).
You have to pass in what you want to turn into a tuple, which is probably your x and y coordinates:
def make_tuple(self):
return (self.x, self.y)

Python 2-dimensional array is behaving strangely

I've been attempting to port a program I've written in C++ to Python. Specifically, it is a program for generating heightmaps which can be exported to 3D models, and which ideally, when viewed, would look like realistic terrain.
The HeightMap class wraps a two-dimensional array of float values. For now I've kept it as integers because it prints nicer, and I haven't had a chance to implement any other features. The glitch I'm having is that when I call set(self, x, y, value), which simply sets the value at x, y to value, with the code "self.rows[y][x] = value", it seems to change the entire column, visiting each member of self.rows and setting the xth member of that array to value.
Here is my code. I am about 90% sure the mistake is somewhere in the 2-array's initialization.
def filledArray(length, value) :
result = []
for i in range(1, length) :
result.append(value)
return result
def resizeArray(array, newLength, nullValue) :
if newLength == len(array) :
return array
result = []
for i in range(0, newLength) :
if i < len(array) :
result.append(array[i])
else :
result.append(nullValue)
return result
class HeightMap:
"""A class that wraps a 2D array for generating height maps"""
def __init__(self) :
self.width = 0
self.height = 0
self.rows = []
def __init__(self, initWidth, initHeight) :
self.clear(initWidth, initHeight);
def clear(self, initWidth, initHeight) :
self.width = initWidth
self.height = initHeight
self.rows = filledArray(initHeight, filledArray(initWidth, 0))
def setHeight(self, newHeight) :
if self.height == newHeight :
return
self.rows = resizeArray(self.rows, newHeight, filledArray(self.width, 0))
def setWidth(self, newWidth) :
if self.width == newWidth :
return
for i in range(0, len(self.rows)) :
self.rows[i] = resizeArray(self.rows[i], newWidth, 0);
self.width = newWidth
def get(self, x, y) :
return self.rows[y][x]
def set(self, x, y, value) :
self.rows[y][x] = value
def add(self, x, y, value) :
self.rows[y][x] += value
def multiply(self, x, y, value) :
self.rows[y][x] *= value
Your problem is that when you call filledArray(initHeight, filledArray(initWidth, 0)) the second argument is passed by reference (this is always the case with python objects). Inside filledArray you need to make a copy of value for each. This will require adding a little bit of additional logic to your function, something along the lines of:
if type(value) == list:
value = list(value)
Or you could do the slightly less pythonic:
type(value)(value)
to create a copy.

Categories

Resources