[BangPypers] Currying in Python 3.0
Anand Balachandran Pillai
abpillai at gmail.com
Thu Dec 11 07:39:53 CET 2008
The new functools module in Python provides a neat
API for doing function currying and doing some other
FP tricks.
The functools.partial function allows you to create
"partial" functions which chops off an argument from
the beginning of the argument list.
Simple example.
>>> def f(x,y): return x + y
>>> import functools.partial
>>>
>>> p = functools.partial(f, 10)
>>> p(20)
30
>>> p(30)
40
This can be extended to do more interesting stuff like,
# Defining a generic summing function which accepts another
# function and applies it to every element of a sequence before
# summing them
>>> def summer(func, l):
... return sum([func(item) for item in l])
Now the summer can be used with partial to create specific
summing functions.
Examples,
>>> simplesummer = functools.partial(summer, lambda x: x)
>>> simplesummer([1,2,3,4])
10
>>> sqrsummer = functools.partial(summer, lambda x: x*x)
>>> sqrsummer([1,2,3,4,5])
55
This allows to write parametrized functions which take in
a parameter and returns the correct summing function.
Example.
>>> def create_summer(typ):
... if typ==0: return functools.partial(summer, lambda x: x)
... elif typ==1: return functools.partial(summer, lambda x:x*x)
And do stuff like,
>>> create_summer(0)([1,2,3,4])
10
>>> create_summer(1)([1,2,3,4])
30
Finally, this makes implementing "currying" in Python almost trivial.
The following is a generic currying function in Python, which
"curries" the passed function <f>.
>>> def curry(f, *args):
... return functools.partial(f, *args)
So, if you have a function which accepts four arguments, say
>>> curry(curry(f, 10), 20)
<functools.partial object at 0x7f2d97bdf890>
>>> curry(curry(curry(f, 10), 20), 30)
<functools.partial object at 0x7f2d97bdf998>
>>> curry(curry(curry(curry(f, 10), 20), 30), 40)
<functools.partial object at 0x7f2d97bdfaa0>
>>> def f(a,b,c,d): return a + b + c + d
>>> curry(curry(curry(curry(f, 10), 20), 30), 40)()
100
#
When extended to operators, it allows some more neat tricks.
>>> mul7= curry(operator.mul, 7)
>>> mul7(2)
14
>>> mul7(21)
147
Of course, the above can all be done in Python <3.0 using lambda,
but functools.partial makes it look neater.
Regards
--
-Anand
More information about the BangPypers
mailing list