Functions are descriptors

I didn’t knew that till i’ve read Ian’s post on decora-descriptors (I guess I can call them that). Actually it’s explained in more details here.

On short, functions have the __get__ method that make them work as descriptors when they are in a class.

I can do this:

>>> class Bar:
...     pass
...
>>> bar = Bar()
>>>
>>> def foo():
...     pass
...
>>> foo
<function foo at 0x00B6F270>
>>>
>>> foo.__get__(None, Bar)
<unbound method Bar.foo>
>>>
>>> foo.__get__(bar, Bar)
<bound method Bar.foo of <__main__.Bar instance at 0x00BCB738>>

Neat !

2 Comments

  1. Posted October 26, 2008 at 10:40 pm | Permalink

    Yeah, cool, eh? That’s how one can add a new bound method to a single instance of a class without screwing up all instances.

    >>> def f(self): print self

    >>> class C(object): pass

    >>> c = C()
    >>> c.f = f.__get__(c, C)
    >>> c.f
    <bound method C.f of >
    >>> c.f()

    >>>

    As opposed to C.f = f, which allows it to show up for all instances of C()

    There’s also a types.MethodType that does pretty much the same thing (I’d guess it’s exactly the same thing, though I haven’t looked).

  2. Robert Lehmann
    Posted October 27, 2008 at 6:20 pm | Permalink

    You can abuse this feature in a pretty clever way — for partial application (`functools.partial`):

    >>> def f(a, b): return a + b

    >>> add1 = f.__get__(1)
    >>> add1(42)
    43
    >>> def g(format, values): return format % values

    >>> helloworld = g.__get__(“Hello %s!”)
    >>> helloworld(“Python”)
    ‘Hello Python!’

    Of course only works with the first positional value.


Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*