Reputation: 211
Consider the Python function line
defined as follows:
def line(m, b):
def inner_function(x):
return m * x + b
return inner_function
This function has the property that for any floats m
and b
, the object line(m, b)
is a Python function, and when line(m, b)
is called on a float x
, it returns a float line(m, b)(x)
. The float line(m, b)(x)
can be interpreted as the value of the line with slope m
and y-intercept b
at the point x
. This is one method for writing a Python function that "depends on parameters" m
and b
.
line
above?Upvotes: 3
Views: 269
Reputation: 155363
This is called a closure, and it's a perfectly reasonable way to write one, as well as one of the most efficient means of doing so (in the CPython reference interpreter anyway).
The only other common pattern I know of is the equivalent of C++'s functors, where a class has the state as attributes, and the additional parameters are passed to __call__
, e.g. to match your case:
class Line:
def __init__(self, m, b):
self.m = m
self.b = b
def __call__(self, x):
return self.m * x + self.b
It's used identically, either creating/storing an instance and reusing it, or as in your example, creating it, using it once, and throwing it away (Line(m, b)(x)
). Functors are slower than closures though (as attribute access is more expensive than reading from nested scope, at least in the CPython reference interpreter), and as you can see, they're more verbose as well, so I'd generally recommend the closure unless your needs require the greater flexibility/power of class instances.
Upvotes: 6
Reputation: 64308
I support @ShaddowRanger's answer. But using partial
is another nice approach.
import functools
def f(m, b, x):
return m * x + b
line = functools.partial(f, 2, 3)
line(5)
=> 13
One thing which is worth pointing out is that lambda
objects, and OP's inner_function
aren't pickleable, whereas line
here, as well as @ShaddowRanger's Line
objects are, which makes them a bit more useful.
Upvotes: 3
Reputation: 49803
This is a little shorter:
def line(m,b):
return lambda x: m*x+b;
Upvotes: 1