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