Currying with instancemethod (was Re: [Python-Dev] accumulator display syntax)

Phillip J. Eby pje at telecommunity.com
Fri Oct 17 17:45:32 EDT 2003


At 10:40 PM 10/17/03 +0200, Alex Martelli wrote:
>Yes, def curry(func, arg): return new.instancemethod(func, arg, object)
>IS indeed way more general than func.__get__(arg) [notably, you get to
>call it repeatedly to curry more than one argument, from the left].  But
>if you have to define a curry function anyway, it's not a huge win vs
>
>def curry(func, arg):
>     def curried(*args): return func(arg, *args)
>     return curried
>
>or indeed more general variations thereof such as
>
>def curry(func, *curried_args):
>     def curried(*args): return func(*(curried_args+args))
>     return curried

It is a big win if the curried function will be used in a 
performance-sensitive way.  Instance method objects don't pay for setting 
up an extra frame object, and for the single curried argument, the 
interpreter even shortcuts some of the instancemethod overhead!  So, if I 
were taking the time to write a currying function, I'd probably implement 
your latter version by chaining instance methods.  (Of course, I'd also 
want to test to find out how many I could chain before the frame overhead 
was less than the chaining overhead.)

Whenever I've run into a performance problem in Python (usually involving 
loops over 10,000+ items), I've almost invariably found that the big 
culprit is how many (Python) function calls happen in the loop.  In such 
cases, execution time is almost linearly proportional to how many function 
calls happen, and inlining functions or resorting to a Pyrex version of the 
same function can often eliminate the performance problem on that basis 
alone.  (For the Pyrex conversion, I have to use PyObject_GetAttr() in 
place of Pyrex's native attribute access, because it otherwise uses 
GetAttrString(), which seems to often make up for the lack of frame 
creation overhead.)




More information about the Python-Dev mailing list