I am trying to override _add_ method. I am getting error :
Point3 = Point1 + Point2
TypeError: unsupported operand type(s) for +: 'Point' and 'Point'
What am I missing? Please help. This was my first Python class.
from math import sqrt
class Point(object):
def __init__(self,x,y,z):
self.x = x
self.y = y
self.z = z
def __str__(self):
return "%i,%i,%i"%(self.x, self.y, self.z)
def _add_(self, other):
TotalX = self.x + other.x
TotalY = self.y + other.y
TotalZ = self.z + other.z
return Point(TotalX, TotalY, TotalZ)
def Distance(self, other):
val =0
val = ((self.x - other.x)**2+ (self.y - other.y)**2 + (self.z - other.z)**2)
return val
print ("Just defined method")
Point1= Point(x=4, y=2, z=9)
Point2= Point(x=5, y=3, z=10)
Point3 = Point1 + Point2
Thanks,
Shruti.
It's __add__, not _add_. All magic methods in Python, such as for addition, use two leading underscores and two trailing underscores. For a detailed reference on the Python data model, including all documented magic methods, please see here.
Related
I'm making a point class in python and I am encountering an error with my makeVectorTo method (a method that takes a second Point as input, and returns a new Vector that goes from starting Point to the second Point). When I try to print it, I am getting this error: AttributeError: 'tuple' object has no attribute 'h'.
How do I get rid of this and print it the way I want?
Here's my code:
class Point:
def __init__(self, x, y):
self.x = float(x)
self.y = float(y)
def makeVectorTo(self, coor):
dx = abs(self.x - coor.x)
dy = abs(self.y - coor.y)
newCoor = (dx, dy)
return newCoor
###Testing Point Class###
vec1 = point1.makeVectorTo(point2)
print(vec1.h, vec1.v, "should be 0,3")
The error looked like this:
Traceback (most recent call last):
File "main.py", line 30, in <module>
print(vec1.h, vec1.v, "should be 0,3")
AttributeError: 'tuple' object has no attribute 'h'
You are returning a tuple, so you should call by index your 'newCoor'
class Point:
def __init__(self, x, y):
self.x = float(x)
self.y = float(y)
def makeVectorTo(self, coor):
dx = abs(self.x - coor.x)
dy = abs(self.y - coor.y)
newCoor = (dx, dy)
return newCoor
point1=Point(1,1)
point2=Point(2,2)
###Testing Point Class###
vec1 = point1.makeVectorTo(point2)
# print(vec1.h, vec1.v, "should be 0,3")
print(vec1[0], vec1[1], "should be 0,3")
As I understand your code, you new to define your Vector Class too
class Point:
def __init__(self, x, y):
self.x = float(x)
self.y = float(y)
def makeVectorTo(self, coor):
dx = abs(self.x - coor.x)
dy = abs(self.y - coor.y)
return Vector(dx, dy) # Note: calling Vector class
# Note: New Vector class
class Vector:
def __init__(self, dx, dy):
self.h = dx
self.v = dy
# Testing
point1 = Point(0, 0)
point2 = Point(0, 3)
vec1 = point1.makeVectorTo(point2)
print(vec1.h, vec1.v, "should be 0.0,3.0") # Note: expect floats here not int
Note: abs only remove -tive sign for a int. If you want to convert a float into proper number then use int or round
I'm writing this code and there is a need to send objects as parameters in functions. My problem is one of the objects needs to be resued with its original values but as I need to return an object from the functions.
I don't know how I can send the answer and keep the original values in the object
safe for reuse. Is there any way to make an object from the class declaration itself?
import math
class Points(object):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __sub__(self, no):
no.x = no.x - self.x
no.y = no.y - self.y
no.z = no.z - self.z
return(no)
def dot(self, no):
ans = (self.x * no.x)+(self.y * no.y)+(self.z * no.z)
return ans
def cross(self, no):
x = (self.y * no.z)-(self.z * no.y)
y = (self.x * no.z)-(self.z * no.x)
z = (self.x * no.y)-(self.y * no.x)
self.x = x
self.y = y
self.z = z
return(self)
def absolute(self):
return pow((self.x ** 2 + self.y ** 2 + self.z ** 2), 0.5)
if __name__ == '__main__':
points = list()
for i in range(4):
a = list(map(float, input().split()))
points.append(a)
a, b, c, d = Points(*points[0]), Points(*points[1]), Points(*points[2]), Points(*points[3])
x = (b - a).cross(c - b)
y = (c - b).cross(d - c)
angle = math.acos(x.dot(y) / (x.absolute() * y.absolute()))
print("%.2f" % math.degrees(angle))
I want to do something like:
def function_name(self,other)
temp.x = self.x + other.x
temp.y = self.y + other.y
return temp
This way both input objects will have their original values but I don't know how to get that temp.
Thanks everyone who helped. I got the answer to what I was looking. I wanted an object to act as a container that can store the class variables,
and I didn't knew I can just make a new object of the class from within it!
import math
class Points(object):
def __init__(self, x, y, z):
self.x=x
self.y=y
self.z=z
def __sub__(self, no):
return Points((self.x-no.x),(self.y-no.y),(self.z-no.z))
def dot(self, no):
return (self.x*no.x)+(self.y*no.y)+(self.z*no.z)
def cross(self, no):
return Points((self.y*no.z-self.z*no.y),(self.z*no.x-self.x*no.z),(self.x*no.y-self.y*no.x))
def absolute(self):
return pow((self.x ** 2 + self.y ** 2 + self.z ** 2), 0.5)
As you can see using points, i.e the constructor for class Points, I can store the result of any operations and can return it as an object while not altering my input objects.
If what you're trying to do is reuse a variable that you have passed to a class object, you can just duplicate it in your __init__ statement, or in the function where you use it.
e.g
class Foo:
def __init__(self, my_var1, my_var2):
self.my_var1 = my_var1
self.my_var2 = my_var2
def bar(self):
bar_var1 = self.my_var1
bar_var2 = self.my_var2
bar_var1 = bar_var1 + bar_var2
return bar_var1
Although, I am a little confused by why you are attempting to return self in your cross function, as self is a class parameter, and you don't seem to be using it in its intended purpose. If you're confused about how you should be using self, a brief read through the python class tutorial might be helpful. However, barring that, I hope this answers your question.
I have the following code:
class Point:
"""Two-Dimensional Point(x, y)"""
def __init__(self, x=0, y=0):
# Initialize the Point instance
self.x = x
self.y = y
#property
def magnitude(self):
# """Return the magnitude of vector from (0,0) to self."""
return math.sqrt(self.x ** 2 + self.y ** 2)
def __str__(self):
return 'Point at ({}, {})'.format(self.x, self.y)
def __repr__(self):
return "Point(x={},y={})".format(self.x, self.y)
The class has a function called magnitude. I want to create a function which can tell the magnitude distance between two points. The following is an expected output:
point1 = Point(2, 3)
point2 = Point(5, 7)
print(point1.magnitude)
3.605551275463989
print(point2.magnitude)
8.605551275463989
print(point1.distance(point2))
5.0
I tried doing something like this:
#classmethod
def distance(self):
pointmag1 = point1.magnitude
pointmag2 = point2.magnitude
if pointmag2 > pointmag1:
return pointmag2 - pointmag1
else:
return pointmag1 - pointmag2
This however return an error TypeError: distance() takes 1 positional argument but 2 were given. I also feel like I am taking an incorrect approach to this as nothing other than point1 or point2 would work. Does anyone have anything which could work better? Thanks.
EDIT: I have mmade the follwoing changes:
#classmethod
def distance(self, self2):
pointmag1 = point1.magnitude
pointmag2 = point2.magnitude
if pointmag2 > pointmag1:
return pointmag2 - pointmag1
else:
return pointmag1 - pointmag2
This however returns 4.996773991578637, instead of 5. Any way to change this?
EDIT: I made the following changes:
#classmethod
def distance(self, self2):
pointmag1 = self.magnitude
pointmag2 = self2.magnitude
if pointmag2 > pointmag1:
return pointmag2 - pointmag1
else:
return pointmag1 - pointmag2
This returns the error TypeError: '>' not supported between instances of 'float' and 'property'
You can implement a custom __sub__ method to find the distance:
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
#property
def magnitude(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
def __sub__(self, _point):
return pow(abs(_point.x-self.x)**2 + abs(_point.y-self.y)**2, 0.5)
point1 = Point(2, 3)
point2 = Point(5, 7)
print(point2-point1)
Output:
5.0
Edit: distance implemented as a method:
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def distance(self, _p2):
return pow(abs(self.x-_p2.x)**2 + abs(self.y-_p2.y)**2, 0.5)
point1 = Point(2, 3)
point2 = Point(5, 7)
print(point1.distance(point2))
Here is the class (from point.py):
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def adjacent(self, pt1, pt2):
return ((pt1.x == pt2.x and abs(pt1.y - pt2.y) == 1) or
(pt1.y == pt2.y and abs(pt1.x - pt2.x) == 1))
def distance_sq(self, p1, p2):
return (p1.x - p2.x)**2 + (p1.y - p2.y)**2
And say I have this function that is in a different file (actions.py):
import point
def find_nearest(world, pt, type):
oftype = [(e, distance_sq(pt, entities.get_position(e)))
for e in worldmodel.get_entities(world) if isinstance(e, type)]
return nearest_entity(of type)
Notice how this function is calling distance_sq from point.py, when I try running this code, it complains that:
AttributeError: 'module' object has no attribute 'distance_sq'
I can't remember the correct syntax for calling a method from a class in a different file! Any help is appreciated! Thanks.
For your Point class, neither of the methods defined refer to the instance (self) at all. You should make these either functions in the point module, or if you prefer to keep them namespaced in the class, make them static methods:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
#staticmethod
def adjacent(pt1, pt2):
return ((pt1.x == pt2.x and abs(pt1.y - pt2.y) == 1) or
(pt1.y == pt2.y and abs(pt1.x - pt2.x) == 1))
#staticmethod
def distance_sq(p1, p2):
return (p1.x - p2.x)**2 + (p1.y - p2.y)**2
Then import the Point class from point if you use the staticmethod approach:
from point import Point
... Point.distance_sq(pt, entities.get_position(e))
Or import point and use point.distance_sq if you use functions instead.
Possibly a better approach, if both pt and entities.get_position(e) are instances of Point, would be to make pt1 in both methods always be the current instance:
def adjacent(self, point):
return (
(self.x == point.x and abs(self.y - point.y) == 1) or
(self.y == point.y and abs(self.x - point.x) == 1)
)
def distance_sq(self, point):
return (self.x - point.x)**2 + (self.y - point.y)**2
Then you don't need to import point at all, just do:
pt.distance_sq(entities.get_position(e))
You can not call a member method of a class directly without creating an instance of that class first. It looks like your distance_sq method should be outside class declaration like:
In point.py:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def adjacent(self, pt1, pt2):
return ((pt1.x == pt2.x and abs(pt1.y - pt2.y) == 1) or
(pt1.y == pt2.y and abs(pt1.x - pt2.x) == 1))
def distance_sq(p1, p2):
return (p1.x - p2.x)**2 + (p1.y - p2.y)**2
Then you can call this function like:
import point
point.distance_sq(point1, point2)
Or, the good way will be to create a classmethod like:
In point.py:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def adjacent(self, pt1, pt2):
return ((pt1.x == pt2.x and abs(pt1.y - pt2.y) == 1) or
(pt1.y == pt2.y and abs(pt1.x - pt2.x) == 1))
#classmethod
def distance_sq(cls, p1, p2):
return (p1.x - p2.x)**2 + (p1.y - p2.y)**2
Then, call it like:
import point
point.Point.distance_sq(point1, point2)
One of my exercises says to write an add method for Points that works with either a Point object or a tuple:
If the second operand is a Point, the method should return a new Point whose x coordinate is the sum of the x coordinates of the operands, and likewise for the y coordinates.
If the second operand is a tuple, the method should add the first element of the tuple to the x coordinate and the second element to the y coordinate, and return a new Point with the result.
This how far I got and I'm not sure if the tuple portion of my code is accurate. Can someone shed some light how I would call this program for the tuple portion. I think I nailed the first part.
Here is my code:
Class Point():
def__add__(self,other):
if isinstance(other,Point):
return self.add_point(other)
else:
return self.print_point(other)
def add_point(self,other):
totalx = self.x + other.x
totaly = self.y + other.y
total = ('%d, %d') % (totalx, totaly)
return total
def print_point(self):
print ('%d, %d) % (self.x, self.y)
blank = Point()
blank.x = 3
blank.y = 5
blank1 = Point()
blank1.x = 5
blank1.y = 6
That's what I've built so far and I'm not sure how to actually run this with the tuple part. I know if it did blank + blank1 the if portion would run and call the add_point function but how do I initiate the tuple. I'm not sure if I wrote this correctly... please assist.
You can simply derive your class from the tuple (or just implement __getitem__).
class Point(tuple):
def __new__(cls, x, y):
return tuple.__new__(cls, (x, y))
def __add__(self, other):
return Point(self[0] + other[0], self[1] + other[1])
def __repr__(self):
return 'Point({0}, {1})'.format(self[0], self[1])
p = Point(1, 1)
print p + Point(5, 5) # Point(6, 6)
print p + (5, 5) # Point(6, 6)
Alternatively, if you want to be able to use point.x and point.y syntax, you could implement the following:
class Point():
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
if isinstance(other, Point):
return Point(self.x + other.x, self.y + other.y)
elif isinstance(other, tuple):
return Point(self.x + other[0], self.y + other[1])
else:
raise TypeError("unsupported operand type(s) for +: 'Point' and '{0}'".format(type(other)))
def __repr__(self):
return u'Point ({0}, {1})'.format(self.x, self.y) #Remove the u if you're using Python 3