Python, in particular, across most programming languages, really does not differentiate much between functions and methods.
What you declare is true: "methods are functions that are unique to the classes they are implemented in" -
And that makes for the indentation difference: since methods are inside a class, they are indented inside the class
statement block.
When you create a simple class, and retrieve a method from it directly, it is actually a function (in python 3 - it worked differently in old Python 2.x):
from types import FunctionType
class A:
def b(self):
pass
print(A.b, type(A.b) is FunctionType)
Prints:
<function A.b at 0x...> True
So, in Python, a "method" is really and literally a function!
It will work differently when retrieved from an instance of the class it is declared on.
[optional complicated paragraph] Then, Python wraps it with what can be described as "a lazy object callable that will insert the instance it is bound to as first argument to the underlying function when called." Once you can make sense of this phrase, you can check "seasoned Pythonista" in your CV.
What it means is simply that "self" will appear "magically" when calling the method, and moreover, one can go back to the original function by looking at the method's .__func__
attribute.
So, given the same class A
above:
In [52]: print(A().b, type(A().b), type(A().b) is FunctionType)
<bound method A.b of <__main__.A object at 0x...>> <class 'method'> False
In [53]: print(A().b.__func__, type(A().b.__func__), type(A().b.__func__) is FunctionType)
<function A.b at 0x...> <class 'function'> True
Note that in these examples I instantiate a new object of the class A
at each time, by writing A()
, while in the first example, I retrieve b
directly from the class, without parenthesis: A.b
As I stated in the beggining of the text: be aware that the fact a plain function can be used as a method is particular to Python, and both kinds of objects will likely have some differences in other programming languages. The idea however, will remain the same: a method will always "know" about the instance from where it was retrieved.