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
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).
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.