Actually, methods and functions in Python are exactly the same thing!
It matters not one bit where it is defined. What matters is how it is looked up.
def defined_outside(*args):
return args
class C:
def defined_inside(*args):
return args
C.defined_outside = defined_outside
defined_inside = C.defined_inside
instance = C()
print( defined_inside (1,2))
print( defined_outside(1,2))
print(instance.defined_inside (1,2))
print(instance.defined_outside(1,2))
which gives the output
(1, 2)
(1, 2)
(<__main__.C object at 0x7f0c80d417f0>, 1, 2)
(<__main__.C object at 0x7f0c80d417f0>, 1, 2)
(This will only work in Python 3: Two of these will produce a TypeError
in Python 2.)
What is important to notice about the output is that, in the first two cases, the functions receive two arguments: 1
and 2
. In the last two cases they receive three arguments: instance
, 1
and 2
.
In the cases where instance
is passed to the function, the function is behaving like a method. In the cases where instance
is not passed in, the function is behaving like a plain function. But notice that both behaviours are exhibited by both the function which was defined inside the classe and the one which was defined outside the class.
What matters is how the function was looked up. If it was looked up as an attribute of an instance of a class, then the function behaves like a method; otherwise it behaves like a free function.
[Incidentally, this binding behaviour only works for pure Python functions; it does not work for functions defined using the Python/C API. The latter always behave like functions and never like methods:
C.dir = dir
instance.dir()
will give you a directory of the global scope, not of instance
, indicating that dir
recived zero arguments, rather that receiving instance
as an argument.
]