Methods versus functions [was Re: Objects in Python]

Steven D'Aprano steve+comp.lang.python at pearwood.info
Thu Aug 23 00:07:00 EDT 2012


On Wed, 22 Aug 2012 21:46:29 +0100, Mark Lawrence wrote:

>> On 22/08/2012 20:45, lipska the kat wrote:
>>>
>>> compare this to a function declaration in Python
>>>
>>> def foo(self):
[...]
> Looking at the self I'm assuming that's a method and not a function.


Actually, it is a function. It doesn't get turned into a method until you 
try to use it.

The way methods work in Python is this:

Function objects are created by the "def" statement, regardless of 
whether that is inside a class or not. So:

class X(object):
    def spam(self, value):
        pass

creates a single function object which takes one argument, self, and 
sticks in in the class namespace X.__dict__['spam'] = spam

When you look up the name "spam" on an X instance:

x = X()
x.spam(42)

Python does it's usual attribute lookup stuff, finds the name "spam" in 
the class namespace, and extracts the function object. So far that's just 
ordinary attribute access. This is where it gets interesting...

Function objects are *descriptors*, which means that they have a __get__ 
method:

py> (lambda x: None).__get__
<method-wrapper '__get__' of function object at 0xb71bd77c>

Python sees that __get__ method and calls it with some appropriate 
arguments (the class object and the instance object, I believe) and the 
__get__ method constructs a method on the fly, handles the automatic bind-
instance-to-self magic, and returns the method object. And then finally 
Python calls the method object with whatever arguments you provided.

As they say, "You can solve any problem in computer science with 
sufficient layers of indirection". This descriptor protocol, as they call 
it, is the mechanism behind methods, class methods, static methods, 
properties, and probably other things as well.

You can do all sorts of funky things with descriptors -- google for 
"descriptor protocol", "data descriptor", "non-data descriptor" etc. if 
you are interested. Here's a trivial, but useful, one:

http://code.activestate.com/recipes/577030-dualmethod-descriptor/


-- 
Steven



More information about the Python-list mailing list