AttributeError: 'list' object has no attribute 'dist' - python

I have been working on an assignment for one of my introductory classes. I am almost done with my code and but I keep getting "AttributeError: 'tuple' object has no attribute 'dist'." I understand that the problem starts from midpt function and that I need to return an instance of the class instead of the tuple; however, I have not been able to do that. Could you please take a look at my code? It would be much appreciated.
'''
import math
class Point(object):
# The contructor for Point class
def __init__(self, x = 0, y = 0):
self.x = float(x)
self.y = float(y)
# The getter for x
#property
def x(self):
return self._x
# The setter for x
#x.setter
def x(self, value):
self._x = value
# The getter for y
#property
def y(self):
return self._y
# The setter for y
#y.setter
def y(self, value):
self._y = value
# Function for getting the distance between two points
def dist(self, other):
xVar = (other.x - self.x) ** 2
yVar = (other.y - self.x) ** 2
equation = xVar + yVar
distance = math.sqrt(equation)
return distance
# Function for getting the midpoint
def midpt(self, other):
xVar = (other.x - self.x) / 2
yVar = (other.y - self.y) / 2
midpoint = (xVar,yVar)
return midpoint
# Magic function for printing
def __str__(self):
return "({},{})".format(self.x, self.y)
##########################################################
# ***DO NOT MODIFY OR REMOVE ANYTHING BELOW THIS POINT!***
# Create some points
p1 = Point()
p2 = Point(3, 0)
p3 = Point(3, 4)
# Display them
print("p1:", p1)
print("p2:", p2)
print("p3:", p3)
# Calculate and display some distances
print("distance from p1 to p2:", p1.dist(p2))
print("distance from p2 to p3:", p2.dist(p3))
print("distance from p1 to p3:", p1.dist(p3))
# Calculate and display some midpoints
print("midpt of p1 and p2:", p1.midpt(p2))
print("midpt of p2 and p3:", p2.midpt(p3))
print("midpt of p1 and p3:", p1.midpt(p3))
# Just a few more things...
p4 = p1.midpt(p3)
print("p4:", p4)
print("distance from p4 to p1:", p4.dist(p1))

You might want to change midpoint = (xVar,yVar) to midpoint = Point(xVar, yVar).
In this way, p4 is a Point (and not a tuple!) instance, and you can call the dist method on it.

Related

How can we set inheritance object in python

I am having a problem in simple code I wrote
Class Point has x and y values
Class square (Point) includes 4 points : p1,p2,p3,p4
I am trying to update x value of p1 for example with sq1.p1.set_x(num1) and failed.
I tried to work with public defnition but also failed
Whot is my problem ? Thanks
class Point:
def __init__(self,x=0,y=0):
self.__x = x
self.__y = y
def get_x(self):
return self.__x
def get_y(self):
return self.__y
def set_x(self,x=0):
self.__x = x
def set_y(self,y=0):
self.__y = y
class Square (Point):
def __init__(self,p1,p2,p3,p4):
self.__p1 = p1
self.__p2 = p2
self.__p3 = p3
self.__p4 = p4
def get_p1(self):
return self.__p1
def get_p2(self):
return self.__p2
def get_p3(self):
return self.__p3
def get_p4(self):
return self.__p4
def set_p1(self,p1):
self.__p1 = p1
def set_p2(self,p2):
self.__p2 = p2
def set_p3(self,p1):
self.__p3 = p3
def set_p4(self,p4):
self.__p4 = p4
def main():
p1 = Point(2,0)
p2 = Point(2,2)
p3 = Point(0,2)
p4 = Point(0,0)
sq1 = Square(p1,p2,p3,p4)
sq1.p1.set_x(4) # this line failing
if __name__ == "__main__":
main()
Replace
sq1.p1.set_x(4) # this line failing
with
sq1.get_p1().set_x(4)
This is because class Square doesn't have a p1 property (it has a __p1 property, but not p1).

How to add a distance method

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))

Method That Calculates Slope In Python

I'm trying to learn Object Oriented Programming in Python. To do this I need to create a method that calculates the slope of a line, which joins the origin to a point. (I think) we're assuming that the origin is (0,0). For example:
Point(4, 10).slopeFromOrigin()
2.5
Point(12, -3).slopeFromOrigin()
-0.25
Point(-6, 0).slopeFromOrigin()
0
And we're using the equation slope = (Y2 - Y1) / (X2 - X1) to calculate the slope. Also, since dividing by 0 isn't allowed, we need to return None when the method fails. Here's what I tried:
class Point:
#Point class for representing and manipulating x,y coordinates
def __init__(self, initX, initY):
#Create a new point at the given coordinates
self.x = initX
self.y = initY
def getX(self):
return self.x
def getY(self):
return self.y
def distanceFromOrigin(self):
return ((self.x ** 2) + (self.y ** 2)) ** 0.5
#define a method called slopeFromOrigin here
def slopeFromOrigin(self):
#set origin values for x and y (0,0)
self.x = 0
self.y = 0
#slope = (Y2 - Y1) / (X2 - X1)
if (Point(x) - self.x) == 0:
return None
else:
return (Point(y) - self.y) / (Point(x) - self.x)
#some tests to check our code
from test import testEqual
testEqual( Point(4, 10).slopeFromOrigin(), 2.5 )
testEqual( Point(5, 10).slopeFromOrigin(), 2 )
testEqual( Point(0, 10).slopeFromOrigin(), None )
testEqual( Point(20, 10).slopeFromOrigin(), 0.5 )
testEqual( Point(20, 20).slopeFromOrigin(), 1 )
testEqual( Point(4, -10).slopeFromOrigin(), -2.5 )
testEqual( Point(-4, -10).slopeFromOrigin(), 2.5 )
testEqual( Point(-6, 0).slopeFromOrigin(), 0 )
As you can see, I'm trying to say that we need the first parameter of Point to be x2, and the second parameter of Point to be y2. I tried it this way and got
NameError: name 'y' is not defined on line 32.
I also tried to get the index values of Point like this:
return (Point[0] - self.y / (Point[1] - self.x)
But that also gave me an error message:
TypeError: 'Point' does not support indexing on line 32
I'm not sure how to get the value of the x and y parameters from Point so that the method works when it's tested. Please share your suggestions if you have any. Thank you.
First problem
self.x = 0
self.y = 0
You just set the current point to the origin. Don't do that. The distance from the origin would then be 0...
Second problem Point(x) and Point(y) are not how you get the values for self.x and self.y.
Then, slope is simply "rise over run". Plus you want to return None when self.x == 0.
So, simply
def slopeFromOrigin(self):
if self.x == 0:
return None
return self.y / self.x
Or even
def slopeFromOrigin(self):
return None if self.x == 0 else self.y / self.x
Or let Python return None on its own
def slopeFromOrigin(self):
if self.x != 0:
return self.y / self.x
I think your confusion lies in that you think you need to somehow define "the origin". If you needed to do that, you would instead have this
origin = Point(0,0)
Point(-6, 0).slopeFromPoint(origin)
if (Point(x) - self.x) == 0:
return None
else:
return (Point(y) - self.y) / (Point(x) - self.x)
As you can see, I'm trying to say that we need the first parameter of Point to be x2, and the second parameter of Point to be y2. I tried it this way and got
NameError: name 'y' is not defined on line 32.
You're trying to access the value of y, which is a global variable that you haven't assigned yet.
I also tried to get the index values of Point like this:
return (Point[0] - self.y / (Point[1] - self.x)
Two problems:
"Point" is a class, not an object (which is an instance of an object).
Even if you've put an object instead, Point is not an list-like object. In order to access an item using index like variableName[index], the class of the variableName must have an implementation for __getitem__(self, key). For example:
>>> class GoodListClass:
... def __init__(self, list):
... self.myList = list
... def __getitem__(self, key):
... return self.myList[key]
...
>>> class BadListClass:
... def __init__(self, list):
... self.myList = list
...
>>> someList = range(10)
>>> goodListObject = GoodListClass(someList)
>>> badListObject = BadListClass(someList)
>>> print(goodListObject[2])
2
>>> print(badListObject[2])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: BadListClass instance has no attribute '__getitem__'

Tuple Class object takes no values

I create an instance of class Vector2 with line AB = Vector2.from_points(A, B)
But python errors out with TypeError: object() takes no parameters
on line AB = Vector2.from_points(A,B)
and on line return Vector2(cls, P2[0]-P1[0], P2[1]-P1[1])
so I figured maybe the book is wrong (I'm looking at examples in a book). I subtract the Vector2 and cls from the def from_points statement so that...
this is how the new line reads: return (P2[0]-P1[0], P2[1]-P1[1])
When I do this a receive the vector value from def from_points equal too (5, 10)
But then python errors out on:
print AB.get_magnitude()
with AttributeError: 'tuple' object has no attribute 'get_magnitude'
so without the code related to Vector2 and cls the program won't read AB as a class object but it seems that I'm not formatting it right so it won't go through.
I have been stuck on this for days.
#Vector Test
import math
class Vector2(object):
def _init_(self, x=0.0,y=0.0):
self.x = x
self.y = y
def _str_(self):
return"(%s,%s)"%(self.x,self.y)
#classmethod
def from_points(cls, P1, P2):
return Vector2(cls, P2[0]-P1[0],P2[1]-P1[1])
def get_magnitude(self):
return math.sqrt(self.x**2 + self.y**2)
A = (15.0, 20.0)
B = (20.0, 30.0)
AB = Vector2.from_points(A, B)
print AB
print AB.get_magnitude()
CHANGED CODE:
#Vector Test
import math
class Vector2(object):
def _init_(self, x=0.0,y=0.0):
self.x = x
self.y = y
def _str_(self):
return"(%s,%s)"%(self.x,self.y)
#classmethod
def from_points(cls, P1, P2):
return (P2[0]-P1[0],P2[1]-P1[1])
def get_magnitude(self):
return math.sqrt(self.x**2 + self.y**2)
A = (15.0, 20.0)
B = (20.0, 30.0)
AB = Vector2.from_points(A, B)
print AB
print AB.get_magnitude()
that's (probably) what you mean.
#Vector Test
import math
class Vector2(object):
def __init__(self, x=0.0,y=0.0):
self.x = x
self.y = y
def __str__(self):
return"(%s,%s)"%(self.x,self.y)
#classmethod
def from_points(cls, P1, P2):
return Vector2(P2.x-P1.x,P2.y-P1.y)
def get_magnitude(self):
return math.sqrt(self.x**2 + self.y**2)
A = Vector2(15.0, 20.0)
B = Vector2(20.0, 30.0)
AB = Vector2.from_points(A, B)
print( AB )
print( AB.get_magnitude() )

Add method that works with either a Point Object or a tuple

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

Categories

Resources