Rules to recognize a method?

I can read in the glossary, that the method is a function within or of the class. What are the rules for recognizing a method within a sample of the code?

method
A function which is defined inside a class body. If called as an attribute of an instance of that class, the method will get the instance object as its first argument (which is usually called self). See function and nested scope.

If you see a class definition:

class Board:
     def __init__(self, size: int);
         self.size = size
     def in_bounds(self, x: int, y: int):
         return 0 <= x < self.size and 0 <= y < self.size
     def is_big(self):
         return self.size > 8
     def __str__(self):
         return f"Board(size={self.size})"

Then all the def statements define methods; they are defined within the class body. The class “Board” acts as a namespace for those methods; the methods can only be called with dot notation, using an instance of the Board class, like this:

>>> board = Board(8)  # creates a Board object
>>> board.is_big()    # calls a Board method on that particular object
False

So if you see some code like this x.y() you also know that y is a method rather than a simple function.

If you’re asking, can I tell at runtime (or can my code tell) if it’s dealing with a method or a function?
The answer is: You can. This is one of the things I always liked a lot about Python and which set it apart from most other languages: almost everything is transparent. Python has strong support for introspection:

>>> def fun():
        print("Hello")
>>> type(fun)
<class 'function'>

>>> my_board = Board(8)
>>> type(my_board)
<class '__main__.Board'>

>>> type(Board.is_big)
<class 'function'>
>>> type(my_board.is_big)
<class 'method'>
1 Like

You can use the inspect module as well:

from inspect import ismethod

class A:
    def meth(self):
        pass

ismethod(A().meth)  # True
1 Like

or use callable:

Here’s a use case that finds all methods that starts with “test” in a script:

#scratch.py
def f(x):
    return x*x

def test():
    assert f(4) == 16

if __name__ == "__main__":
    for k,v in globals().items():
        if k.startswith("test") and callable(v):
            v()  # runs the test.

Allways? It couldn’t be for example function in the library? What about tkinker.Tk(), is it also the method? If I apply what Viicos recommends it gives me False.

It all depends what you mean by “method”. Already in this thread I’ve seen three distinct ways of defining methods :slight_smile:

I would stay with the definition in the glossary.

Sorry my example was incorrect, it is now fixed (you need to use an instance of A, not the class itself).

methods are functions, but not the opposite. In your example, test is a function, but not a method.

Here is a more detailed example, covering all cases:

from inspect import isfunction, ismethod

class A:
    @staticmethod
    def static(): ...
    @classmethod
    def clsmethod(cls): ...
    def instmethod(self): ...

A().static
#> <function A.static at 0x7fbbb83b4700>
ismethod(A().static)
#> False
isfunction(A().static)
#> True

A().clsmethod
#> <bound method A.clsmethod of <class '__main__.A'>>
ismethod(A().clsmethod)
#> True
isfunction(A().clsmethod)
#> False

A().instmethod
#> <bound method A.instmethod of <__main__.A object at 0x7fbbb8387b50>>
ismethod(A().instmethod)
#> True
isfunction(A().instmethod)
#> False

Interestingly, clsmethod and instmethod are not considered functions, even if according to the glossary, a method is a function with specific properties.

Now some edge cases:

A().instmethod
#> <bound method A.instmethod of <__main__.A object at 0x7fbbb8387b50>>
A.instmethod
#> <function A.instmethod at 0x7fbbb83b4820>
isfunction(A.instmethod)
#> True

Normal methods (or “instance methods” such as instmethod) are bound to an instance, so accessing them through the class object A returns a function, because no instance was used.

Here are a few equally-reasonable definitions:

  1. Anything called as obj.method()
  2. A function defined within a class
  3. The result of looking up obj.method when type(obj).method is a function
  4. A function defined within a class, but NOT a staticmethod or classmethod

These are all slightly different in their edge cases, and they’re all valid. For example, you could reasonably argue that a classmethod is not a method, but rather a plain function that happens to be connected to a class.

Wikipedia’s definition of “method” simply requires that the function (called “procedure” there) be “associated with” an object. That definition mostly aligns with the notion that a method is what you get when you call obj.method(). The result of inspect.ismethod is actually telling you whether it is a bound method object, which is a different definition.

So… what’s really important here? If I call random.randrange() a method on the random object, is that truly wrong? Does something cease to be a method if you change it from a function to a class or callable object?

3 Likes

I think this is a very “pythonic” reply - I like it a lot. I think for a novice – especially if Python is your first programming language, and you haven’t first learned C++ or learned anything about object-oriented programming – you may be confused about new terms flying around and it’s natural to want more clarity.
But the main thing is never “what should this be called” but “what can I do with this”.

Exactly! Terminology is only useful in so far as it allows you to know what you can do with a thing. Words like “list”, “array”, “iterable”, and so on, all have very specific meanings, but those meanings are useless if you don’t know what you can actually USE those for.

The short and sloppy definition “a method is a function in a class” is probably fine for most purposes, as is the equally short and sloppy “a method is a function called on an object”. Pick whichever you like and go with it.