id() collisions on bound methods [was: metaclass and customization with parameters]

Alex Martelli aleaxit at yahoo.com
Wed Oct 6 06:09:31 EDT 2004


Jeff Epler <jepler at unpythonic.net> wrote:

> Perhaps someone could devise a metaclass that does bound method caching.
> In a few situations, it might be worth having, but I'm not sure if in
> those situations a little
>     c.f = c.f
> in __init__, or manual hosting like 'f=c.f' is not just as appropriate.

You may well be right, but people to have a reasonable aversion to
manual hoisting and similar optimization-oriented boilerplate -- yeah,
it IS simpler to implement than having it happen behind the scene, but
it clutters up applications.

The metaclass you mention could wrap every function in a specialized
descriptor (which would have to know the corresponding name, given at
init time -- __get__ isn't told the name, a design error IMHO) whose
__get__ delegates to the function's and then caches the result in the
instance.

Measurement suggests that with Python 2.3, normal method calls (to a
'def f(): pass' method) take (on my old machine) 0.91 microseconds/call
without precautions; calls with manual caching as you suggest take 0.86;
calls with an automatic caching descriptors, 0.87.  For once, 2.4 is
minimally slower -- 0.96, 0.90, 0.91.  Considering that a typical method
will do more work than just 'pass', doesn't sound like an optimization
worth pursuing, alas.

_Hoisting_, otoh (the f=c.f idea) takes the time down to 0.66 for 2.3,
0.69 for 2.4 -- now THAT is helpful.  Unfortunately I don't know of an
easy way to automate that.  Maybe Hettinger's recipe on a decorator for
automatic hoisting of globals could be tweaked for the purpose...?


Alex



More information about the Python-list mailing list