0

I have defined a class called Point which defines a point in the x, y coordinate system. The definition and methods are shown below. I created my own version of the str method to return the created point in a printable form (required). However, when I try to pass the returned point to another method to determine the distance between two points (p1 and p2), using the call p.DistanceTo(p2), I get the following error from the attempt to parse the string (p2) passed into the method:

AttributeError: Point instance has no attribute 'find'

When I pass in a string defined as p2 should be it works just fine. Any help would be greatly appreciated. Thank you.

Here is the code:

class Point:
    """ Define a Point
    """
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __str__(self):
        return "(" + str(self.x) + "," + str(self.y) + ")"

    def __getitem__(self,i):
        return i

    def __find__(self,j):
        return j

    def DistanceTo(self,p2):
        idx1 = p2.find("(")
        idx2 = p2.find(",")
        idx3 = p2.find(")")

        x2 = int(p2[idx1+1:idx2])
        y2 = int(p2[idx2+1:idx3])

        dist = math.sqrt(math.pow((x2-self.x),2)+math.pow((y2-self.y),2))
        return  dist


p1=Point()

p2=Point(3,4)

print p1.DistanceTo(p2)
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343

3 Answers3

3

You named the method __find__. Remove the double underscores:

def find(self, j):
    return j

You should really only use __...__ "dunder" (double underscore) method names for the Special method names to avoid confusion and future name clashes.

However, you are passing in a Point instance, so just access the attributes directly:

def DistanceTo(self,p2):
    x2 = p2.x
    y2 = p2.y

    dist = math.sqrt(math.pow((x2-self.x),2)+math.pow((y2-self.y),2))
    return  dist

or, further simplified, using the underscore_name style most often used in Python for methods:

def distance_to(self, p2):
    return math.sqrt(math.pow((p2.x - self.x), 2) + math.pow((p2.y - self.y), 2))

You can then remove the __find__ and __getitem__ methods, those look like attempts at making the .DistanceTo() method work.

The full class then becomes:

class Point(object):
    """Define a Point"""

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __str__(self):
        return "({0.x}, {0.y})".format(self)

    def distance_to(self, p2):
        return math.sqrt(math.pow((p2.x - self.x), 2) + math.pow((p2.y - self.y), 2))

using a little more Python idiom for the class (inheriting from object) and the __str__ method (using string formatting).

Now the class behaves as expected:

>>> p1 = Point()
>>> p2 = Point(3,4)
>>> print p1
(0, 0)
>>> print p2
(3, 4)
>>> print p1.distance_to(p2)
5.0

Class instances are not strings, and although they can be converted to strings (when printed for example), you don't need to treat them as strings. Just access their attributes directly.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
1

The method find is not declared in your object, you have to change the find method declaration like this:

...
def find(self,j):
    return j
...

The double underscores are reserved for class operator methods like str, cmp, eq etc... You can get more info about python class here

jvallver
  • 2,230
  • 2
  • 11
  • 20
  • Hey Guys, when I tried that I get this error from my attempt to parse the p2 string: x2 = p2[idx1+1:idx2] TypeError: cannot concatenate 'str' and 'int' objects – user2278537 May 08 '13 at 15:19
  • You need to convert int objects to str if you want to concatenate it with another str. If you want to convert int object to str use the str() builtin function. example: a=1; aConvertedToStr=str(a) – jvallver May 08 '13 at 15:25
  • Thanks to everyone who helped me better understand Python. I like this language! – user2278537 May 08 '13 at 15:31
0

If you intended to have private or semi-private methods in your class rename your function.

If your find method will only be used inside the Point class, rename it to __find. Otherwise you can rename it to _find which tells other developers that this method is intended to be private but they can still use it even though they should not.

Nylo Andy
  • 152
  • 1
  • 9