351

I have this code which calculates the distance between two coordinates. The two functions are both within the same class.

However, how do I call the function distToPoint in the function isNear?

class Coordinates:
    def distToPoint(self, p):
        """
        Use pythagoras to find distance
        (a^2 = b^2 + c^2)
        """
        ...

    def isNear(self, p):
        distToPoint(self, p)
        ...
Peter Mortensen
  • 30,030
  • 21
  • 100
  • 124
Steven
  • 3,753
  • 3
  • 16
  • 11

2 Answers2

548

Since these are member functions, call it as a member function on the instance, self.

def isNear(self, p):
    self.distToPoint(p)
    ...
Jeff Mercado
  • 121,762
  • 30
  • 236
  • 257
67

That doesn't work because distToPoint is inside your class, so you need to prefix it with the classname if you want to refer to it, like this: classname.distToPoint(self, p). You shouldn't do it like that, though. A better way to do it is to refer to the method directly through the class instance (which is the first argument of a class method), like so: self.distToPoint(p).

Aleksi Torhamo
  • 6,122
  • 2
  • 32
  • 42
  • @Aleski. If it's a generic method (common to all instances and without any instance specific variables referenced in the method), could you please explain why one shouldn't use classname.distToPoint(self, p)? – Yugmorf Oct 10 '18 at 04:04
  • 4
    @Yugmorf: There's only one situation where one should use `classname.distToPoint(self, p)`: when you're defining a subclass that overrides `distToPoint`, but needs to call the original. If you tried to call `self.distToPoint(p)` like normal in that case, you'd end up calling the method that you're just defining, and get into an infinite recursion. If not inside a class, there's also only one situation where you'd use `classname.distToPoint(obj, p)` instead of `obj.distToPoint(p)`: if obj might be an instance of the subclass, but you need to call the original `distToPoint` defined *(continued)* – Aleksi Torhamo Oct 10 '18 at 13:30
  • 1
    in `classname` instead of the overridden version in the subclass - but note that this is very hacky and shouldn't be done in general without a *very* good reason. Note that you break subtype polymorphism when you call a method explicitly through a class (in both of the examples above, you specifically *want* to do that). So in short: you should only call a method explicitly through a class when you *need* to circumvent subtype polymorphism for some [good] reason. If the method hasn't been overridden, the two ways are equal, but `self.distToPoint(p)` is shorter and more readable, *(continued)* – Aleksi Torhamo Oct 10 '18 at 13:30
  • so you should definitely still use it. Now, getting to the specifics of your question: if your method doesn't use any instance variables, maybe it should be a classmethod instead? You make those by adding `@classmethod` before the method, and after that you won't get an instance (`self`) as the first argument anymore - instead you get the class, so you should name the first argument eg. `cls` instead. After that, you can call the classmethod either like `obj.distToPoint(p)` or `classname.distToPoint(p)` (note the lack of `obj`). You should *still* probably use *(continued)* – Aleksi Torhamo Oct 10 '18 at 13:31
  • `obj.distToPoint(p)`, though, if you just have a relevant instance on your hands, unless - again - you have some [good] reason to circumvent subtype polymorphism, since the classmethod could've been overridden in a subclass too, in general. Of course, if you don't have a *relevant* instance available, you should by all means call a *classmethod* directly through a class. – Aleksi Torhamo Oct 10 '18 at 13:31
  • @ Aleksi. Thank you for your detailed explanation. – Yugmorf Oct 11 '18 at 01:56