Reputation: 57
Traceback (most recent call last):
line 56, in <module>
distanceToOne = point1.Distance(pointUser)
line 22, in Distance
distance = math.sqrt((self.__x - toPoint.x)**2 +(self.__y - toPoint.y)**2 +(self.__z - toPoint.z)**2)
AttributeError: 'Point' object has no attribute 'x'
For some reason I keep getting the above error message whenever I get to: distanceToOne = point1.Distance(pointUser)
after grabbing my three points to calculate the distance from.
Here is a better view if needed: http://pastie.org/private/vige6oaphkwestdemr5uw
Thanks in advance for your help!
import math
class Point(object):
def __init__(self, x = 0, y = 0, z = 0, description = 'TBD'):
self.__x = x
self.__y = y
self.__z = z
self.__description = description
def SetPoint(self, coords):
self.__x = coords[0]
self.__y = coords[1]
self.__z = coords[2]
def GetPoint(self):
return [self.__x, self.__y, self.__z]
PointCoords = property(GetPoint, SetPoint)
def Distance(self, toPoint):
toPoint.PointCoords[0]
toPoint.PointCoords[1]
toPoint.PointCoords[2]
return math.sqrt(
(self.__x - toPoint.x)**2 +
(self.__y - toPoint.y)**2 +
(self.__z - toPoint.z)**2)
def SetDescription(self, description):
self.__description = description
def GetDescription(self):
return self.__description
PointDescription = property(GetDescription, SetDescription)
if __name__ == "__main__":
print "Program 9: Demonstrate how to define a class"
point2 = Point()
point1 = Point(10, 54, 788, 'Ploto')
point2.PointCoords = 77, 2, 205
point2.PointDescription = 'Mars'
doAnother = "y"
while(doAnother == "y"):
pointX = raw_input("Enter a X Number: ")
pointY = raw_input("Enter a Y Number: ")
pointZ = raw_input("Enter a Z Number: ")
# Constructor - Represent the user's location
pointUser = Point(pointX, pointY, pointZ, 'Sun')
distanceToOne = point1.Distance(pointUser)
distanceToTwo = point2.Distance(pointUser)
# Comparing the two distances between the two to see which one is the closest
if (distanceToOne > distanceToTwo):
closest = point2
else:
closest = point1
print ('You are closest to',closest.PointDescription(), 'which is located at ',closest.PointCoords())
doAnother = raw_input("Do another (y/n)? ").lower()
print ('Good Bye!')
Upvotes: 4
Views: 16727
Reputation: 15433
In the return line of Distance(), __x instead of x (same for y and z), since the instances of the Point class do not have x, y z attributes but they do have __x, __y, __z attributes.
def Distance(self, toPoint):
toPoint.PointCoords[0]
toPoint.PointCoords[1]
toPoint.PointCoords[2]
return math.sqrt(
(self.__x - toPoint.__x)**2 +
(self.__y - toPoint.__y)**2 +
(self.__z - toPoint.__z)**2)
Upvotes: 1
Reputation: 362944
The actual error is due to accessing toPoint.x
, which doesn't exist because you have never defined it.
On a related note, prepending attributes with double underscores activates pythons name mangling feature. The actual attributes will still be publicly accessible at my_point._Point__x
, my_point._Point__y
, etc from outside the class.
As a matter of style, there does not seem to be any reason to use name mangling in this case. The intended use-case of this feature is to avoid clashes with inherited classes, it's not really about trying to make "private" variables (for that, the convention is to use a single underscore to indicate when an attribute is implementation detail).
In your case, I think you should just name (and access) the attributes normally x
, y
, etc. In python we don't normally write getters and setters for class members unless there is a special requirement to do so, because Python is not Java.
Upvotes: 2
Reputation: 87094
Another way to do it is to unpack toPoint.PointCoords
into local variables like this:
def Distance(self, toPoint):
x, y, z = toPoint.PointCoords
return math.sqrt(
(self.__x - x)**2 +
(self.__y - y)**2 +
(self.__z - z)**2)
Upvotes: 0
Reputation: 109606
This example uses the namedtuple class from collections. I've also re-written the class to implement it (it should still work with your existing program).
Also note that python generally does not use setters or getters. In fact. you set the description directly in your program (as you should) rather than having used your setter function.
import math
from collections import namedtuple
point = namedtuple('point', ['x', 'y', 'z'])
class Point(object):
def __init__(self, x=0, y=0, z=0, description='TBD'):
self.point = point(x, y, z)
self.__description = description
def __repr__(self):
return str(self.point)
def set_point(self, coords):
self.point = point(coords)
def get_point(self):
p = self.point
return p.x, p.y, p.z
def distance(self, toPoint):
p = toPoint.point
return math.sqrt(
(self.point.x - p.x)**2 +
(self.point.y - p.y)**2 +
(self.point.z - p.z)**2)
def set_description(self, description):
# Python generally does not use getters/setters.
self.description = description
def get_description(self):
# Python generally does not use getters/setters.
return self.description
Upvotes: 0
Reputation: 19329
You could make the x
, y
and z
attributes of your Point class publicly accessible. If you want the client to be able to read but not write to them, you can use a property. For example:
class Point(object):
def __init__(self, x = 0, y = 0, z = 0, description = 'TBD'):
self.__x = x
self.__y = y
self.__z = z
self.__description = description
@property
def x(self):
return self.__x
@property
def y(self):
return self.__y
@property
def z(self):
return self.__z
...
You can then access x, y and z without the leading underscores and your Distance function should work.
>>> p = Point(1, 2, 3, 'Dummy')
>>> p.x
1
>>> p.y
2
>>> p.z
3
>>> p.x = 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
Upvotes: 0