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
Related
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 a question but I don't know exactly how to explain it, so let me put some code here:
class 2DVector:
def __init__(self, x, y):
self.x = x
self.y = y
def multiply(self, scalar):
self.x *= scalar
self.y *= scalar
is it posible to do something like this
vector1 = 2DVector(1, 1).multiply(3)
# x == 3, y == 3
or do I always have to do it like this
vector2 = 2DVector(1, 1)
# x == 1, y == 1
vector2.multiply(3)
# x == 3, y == 3
Adding return self at the end of the multiply method allows you to use the first option:
class TwoDVector:
def __init__(self, x, y):
self.x = x
self.y = y
def multiply(self, scalar):
self.x *= scalar
self.y *= scalar
return self
if __name__ == '__main__':
vector = TwoDVector(2, 3).multiply(2)
# vector.x == 4, vector.y == 6
They are equivalent in that they both scale the vector.
But your first example is not very useful it doesn't keep a reference to the class instance. Instead it keeps a reference to the return value of multiply (which is just None) so your vector reference is lost.
As mentioned you could modify multiply to return self.
You could also add a scale factor to the constructor:
class 2DVector:
def __init__(self, x, y, scale=1):
self.x = x
self.y = y
self.multiply(scale)
# scales vector to (3, 3)
vector1 = 2DVector(1, 1, 3)
If you want to use vector2.multiply(3) directly, you need to adapt your method and return something.
def multiply(self, scalar):
self.x *= scalar
self.y *= scalar
return self
But I do not like this solution and prefer :
def multiply(self, scalar):
return 2DVector(self.x * scalar, self.y * scalar)
and treat vector as immutables objects.
Or keeping your first implementation and do
vector2 = 2DVector(1, 1)
# x == 1, y == 1
vector2.multiply(3)
# x == 3, y == 3
I am trying to create some custom Python classes for my application. When I try to debug my code I can not pick the instances of my custom classes, I receive the error "Object XXX is not picklable".
I found this page https://docs.python.org/3/library/pickle.html#what-can-be-pickled-and-unpickled but I don't understand how I should implement the methods that make my class picklable.
For example how would you modify the following classes so that I can pick instances of them?
class Point3D:
def __init__ (self, x, y, z):
self.x = x
self.y = y
self.z = z
def move(self, vector):
self.x += vector.x
self.y += vector.y
self.z += vector.z
return
def isValidPoint(self):
isNotValid = False
isNotValid = math.isnan(self.x) or math.isnan(self.y) or math.isnan(self.z)
return not isNotValid
And
class PointCloud3D:
def __init__ (self):
self.points = []
def getNumberOfPoints(self):
return len(self.points)
def addPoint(self, point):
self.points.append(point)
return
def addPointCloud3D(self, additionalPointCloud3D):
for self.point in additionalPointCloud3D:
self.addPoint(point)
def getCloudCenter(self):
numberOfPoints = self.getNumberOfPoints()
centersSumX = 0
centersSumY = 0
centersSumZ = 0
for point in self.points:
centersSumX = centersSumX + point.x
centersSumY = centersSumY + point.y
centersSumZ = centersSumZ + point.z
centerX = centersSumX/numberOfPoints
centerY = centersSumY/numberOfPoints
centerZ = centersSumZ/numberOfPoints
center = Point3D(float(centerX), float(centerY) , float(centerZ))
return center
While here you can find the code that I am trying to debug:
from classDatabase import Point3D, PointCloud3D
testPoint1 = Point3D(1.5, 0.2, 2.3)
testPoint2 = Point3D(3.5, 1.2, 5.3)
testPointCloud3D = PointCloud3D()
testPointCloud3D.addPoint(testPoint1)
testPointCloud3D.addPoint(testPoint2)
Finally a screenshot of the issue:
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__'
I'm new to python, and programming in general and am struggling to understand why I can't access the x, y coordinates of the list I created ranlist to use as variables in my math module distance formula.
Here is the entirety of my code, however the step of defining the function closestpt is where I am hung up, and within the function, ranlist.x, ranlist.y is where I get an
AttributeError: list object has no attribute 'x'
Can someone explain to me why ranlist does not have 'x' and 'y' as attributes, and how I can access the x,y points in the list ranlist? When I step through the code and debug I can see the random float values generated
import math
class Point():
def __init__(self, x, y, z=0):
self.x=x
self.y=y
self.z=z
self.dem=2
if (z!=0):
self.dem=3
def print_coordinate(self):
print "The x coordinate is %s, the y coordinate is %s, and the z coordinate is %s" % (self.x, self.y, self.z)
def calc_distance(self, next1):
try:
if (self.z==0):
dx = self.x - next1.x
dy = self.y - next1.y
return math.hypot(dx,dy)
else:
threedist = ((self.x - next1.x)^2 + (self.y - next1.y)^2 + (self.z - next1.z)^2)
return math.sqrt(threedist)
except(SyntaxError, IndexError, TypeError) as e:
print e
cord1 = Point(0,1,4)
cord2 = Point(0,4,0)
print cord1.print_coordinate()
print cord1.calc_distance(cord2)
import random
a = 10
b = 20
val = random.uniform(a,b)
ranlist = []
def ranpoint(num_point, dimension, lower_bound, upper_bound):
for i in range(num_point):
x = random.uniform(lower_bound, upper_bound)
y = random.uniform(lower_bound, upper_bound)
ranlist.append(Point(x,y,0))
return ranlist
print ranpoint
print ranpoint(100, "2d", 0, 100)
rantest = ranpoint(100, '2d', 0, 100)
def closestpt():
cordt = Point(50,50)
dist1 = []
for i in range(0, 100):
ndx = cordt.x - ranlist.x
ndy = cordt.y - ranlist.y
dist2 = math.hypot(ndx,ndy)
dist1.append(dist2)
return dist1
print closestpt()
You have ranlist which is a list. You append a Point to it. So now ranlist has 1 object inside it of type Point.
To access this object you could run ranlist[0].x and ranlist[0].y which will access the first member of the list (in index 0) and retrieve the value of x and y respectively.