I am looking for a way to partially apply functions in python that is simple to understand, readable, resusable and as little error prone to coder mistakes as possible. Most of all I want the style to be as performant as possible - less frames on the stack is nice, and less memory footprint for the partially applied functions is also desirable. I have considered 4 styles and written examples below:
import functools
def multiplier(m):
def inner(x):
return m * x
return inner
def divide(n,d):
return n/d
def divider(d):
return functools.partial(divide,d=d)
times2 = multiplier(2)
print(times2(3)) # 6
by2 = divider(2)
print(by2(6)) # 3.0
by3 = functools.partial(divide,d=3)
print(by3(9)) # 3.0
by4 = lambda n: divide(n,4)
print(by4(12)) # 3.0
My analysis of them are:
times2
is a nested thing. I guess python makes a closure with the m
bound, and everything is nice. The code is readable (I think) and simple to understand. No external libraries. This is the style I use today.
by2
has an explicit named function which makes it simple for the user. It uses functools, so it gives you extra imports. I like this style to some extent since it is transparent, and give me the option to use divide
in other ways if I want to. Contrast this with inner
which is not reachable.
by3
is like by2
, but forces the reader of the code to be comfortable with functools.partial
since they have it right in the face. what I like less is that PyCharm cant give my tooltips with what the arguments to functools.partial
should be, since they are effectively arguments to by3
. I have to know the signature of divide
myself everytime I define some new partial application.
by4
is simple to type, since I can get autocompletion. It needs no import of functools
. I think it looks non-pythonic though. Also, I always feel uncomfortable about scoping of variables / closures with lambdas work in python. Never sure how that behaves....
What is the logical difference between the styles and how does that affect memory and CPU?