How to modify a variable inside a lambda function? - python

I am trying to do something like this:
def myFunc(y):
aVariable = "a"
bVariable = "b"
y(aVariable,bVariable)
def main():
myFunc(lambda a,b: a+=b)
and expecting the output to be "ab".
Instead I get the following error:
File "<stdin>", line 7
myFunc(lambda x, y: x += y)
^
SyntaxError: invalid syntax

Only expressions are allowed in the body of a lambda function; a += b is an augmented assignment statement, when compiled, this will lead to a SyntaxError as the grammar doesn't allow it.
You can either change it to simply return the addition:
lambda a,b: a+b
and then proceed to set the result of calling it to a appropriately:
a = y(aVariable,bVariable)
You could of course resort to using the function that is used for that operation. Though you could directly do lambda a, b: a.__iadd__(b), this is clunky and using dunders like this isn't the best practice. Instead, you should use the appropriate operation from the operator module.
The iadd function from operator allows you to bypass this "restriction" if you truly need to. Function calls are expressions, as such, it is allowed to use them in the body of the lambda function. A simple import is needed:
from operator import iadd
and then, redefine the lambda passed to myFunc to use iadd:
myFunc(lambda a,b: iadd(a, b))
Adding these all together while also adding appropriate returns in myFunc and main:
from operator import iadd
def myFunc(y):
aVariable = "a"
bVariable = "b"
return y(aVariable,bVariable)
def main():
return myFunc(lambda a,b: iadd(a, b))
results in ab when main is called.

Related

How can I call a lambda without defining it as a function?

For lambda functions in the following code,
def myfunc(n):
return lambda a : a * n
mydoubler = myfunc(2)
print(mydoubler(11))
I am trying to understand why mydoubler becomes <class 'function'> and how I can call mydoubler(11) without defining it as a function.
A lambda is a function, but with only one expression (line of code).
That expression is executed when the function is called, and the result is returned.
So the equivalent of this lambda:
double = lambda x: x * 2
is this def function:
def double(x):
return x * 2
You can read more here
A lambda is a function, so your code is doing something like
def myfunc(n):
def result(a):
return a * n
return result # returns a function
mydoubler = myfunc(2)
print(f(11))
You're asking how to call mydoubler without defining it as a function, which isn't the clearest question, but you can call it without naming it like so
print( myfunc(2)(11) )
Your myfunc is returning a lambda. Lambda is a small anonymous function. A lambda can take any number of arguments, but can only have one expression.
So after execution of the 3rd line, your mydoubler will become a lambda that's why when you try print(type(mydoubler)) it will return <class 'function'>.
Also in order to call mydoubler with 11, it must be function.
A lambda expression, like a def statement, defines functions. Your code could be equivalently written as
def myfunc(n):
def _(a):
return a * n
return _
mydoubler = myfunc(2)
print(mydoubler(11))
Because the inner function is simple enough to be defined as a single expression, using a lambda expression saves you the trouble of coming up with the otherwise unused name the def statement requires.
The key here is that the inner function closes over the value of n, so that the function returned by myfunc retains a reference to the value of the argument passed to myfunc. That is, mydoubler is hard-coded to multiply its argument by 2, rather than whatever value n may get later. (Indeed, the purpose of the closure is to create a new variable n used by the inner function, one which cannot easily be changed from outside myfunc.)
using decorator you can achive this
from functools import wraps
def decorator_func_with_args(arg1):
def decorator(f):
#wraps(f)
def wrapper(val):
result = f(val)
return result(arg1)
return wrapper
return decorator
#decorator_func_with_args(arg1=2)
def myfunc(n):
return lambda arg:arg*n
result = myfunc(1211)
print(result)
output
2422
Do you mean this?
mydoubler = lambda a : a * 2
mydoubler(11)

What is the mechanism behind a function that contains a lambda expression? (Python)

During a tutorial I stumbled upon the following example.
I get the general purpose and mechanism of functions. They get parameters such as "a", "b" and "c" (example below).
But how come that we can "link" the function to an object f that itself can contain 0 as parameters that will then be computed by our lambda expression?
def build_quadratic_function(a,b,c):
return lambda x: a*x**2 + b*x+c
f = build_quadratic_function(2,3,-5)
f(0)
yields:
-5
In layman words, how does the function "know" that 0 must be read by the lambda expression that is contained in the function?
Can somebody explain the mechanism behind it?
Thank you!
def build_quadratic_function(a,b,c):
return lambda x: a*x**2 + b*x + c
is (in all important aspects) equivalent to
def build_quadratic_function(a,b,c):
def func(x):
return a*x**2 + b*x + c
return func
In both cases, the inner function, be it an anonymous one or not, is holding onto the variables in the enclosing scope. You have discovered so called closures.
>>> import inspect
>>> f = build_quadratic_function(2, 3, -5)
>>> inspect.getclosurevars(f)
ClosureVars(nonlocals={'a': 2, 'b': 3, 'c': -5}, globals={}, builtins={}, unbound=set())
A very similar example can be found in the documentation.
Lambdas are small anonymous functions. They can be used wherever function objects are required. They are syntactically restricted to a single expression. Semantically, they are just syntactic sugar for a normal function definition. Like nested function definitions, lambda functions can reference variables from the containing scope.
Therefore if you define a custom function that contains a lambda, and then fix its parameters, it's essentially the same as defining a lambda function and then passing the expression.
For the sake of your example:
def build_quadratic_function(a,b,c):
return lambda x: a*x**2 + b*x+c
f = build_quadratic_function(2,3,-5)
Would create the same output as:
f = lambda x: 2*x**2 + 3*x - 5
In either case, when you call f(0) then the expression gets evaluated with value 0 returning -5.
2*0**2 + 3*0 - 5 = - 5
The improvement using a custom function over the simple definition of the lambda itself is you can modify the a, b and c parameters.
This isn't a lambda specific thing. Its a "closure" and can be done with a regular function also. In fact, a lambda is just an anonymous function. Its it restricted to implementing an expression instead of full python statements, but that's only the case because of python parsing issues. So, this is the same thing
def build_quadratic_function(a,b,c):
def inner(x):
return a*x**2 + b*x+c
return inner
inner uses variables from the enclosing function. When build_quadratic_function returns inner, the current objects in a, b and c are bound to inner. Later, when inner(someval) is called, those bound objects to a, b and c are used. x, which is a parameter to inner needs to be supplied on each call.
You can get the inner function once and use it many times with the same values.
func = build_quadratic_function(1,2,3)
for i in range(10):
print(func(i))
A lambda function is a small anonymous function. (function with no name)
f = build_quadratic_function(2,3,-5)
Till this point, f is equal to the return value of build_quadratic_function, which is another function(lambda in this case)!
f(0) calls the lambda which is waiting

How to take the logical and of a list of boolean functions in python

Say I have a list of functions li = [fun1, fun2, ..., funk] that take one argument and return a boolean. I'd like to compose them into a single function that returns the logical and of the return values of each of the fun's when evaluated at its argument. (in other words I'd like to have fun(x) = fun1(x) and fun2(x) and ... and funk(x).)
Is there an elegant way of doing this?
Use all to create the composite function
def func(x, lst):
#lst is the list of functions and x is used as an argument for functions
return all(fun(x) for fun in lst)
And then call it as
func(x,[fun1, fun2, fun3,...., funk])
If a lambda function is needed, you can do the following, however it is against PEP-8 guidelines
Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier.
func = lambda x:all(fun(x) for fun in lst)
And call it as
func(x)
all will do it
all(func(x) for func in li)

Return function with function

I would like to do something like the following:
def getFunction(params):
f= lambda x:
do stuff with params and x
return f
I get invalid syntax on this. What is the Pythonic/correct way to do it?
This way I can call f(x) without having to call f(x,params) which is a little more messy IMO.
A lambda expression is a very limited way of creating a function, you can't have multiple lines/expressions (per the tutorial, "They are syntactically restricted to a single expression"). However, you can nest standard function definitions:
def getFunction(params):
def to_return(x):
# do stuff with params and x
return to_return
Functions are first-class objects in Python, so once defined you can pass to_return around exactly as you can with a function created using lambda, and either way they get access to the "closure" variables (see e.g. Why aren't python nested functions called closures?).
It looks like what you're actually trying to do is partial function application, for which functools provides a solution. For example, if you have a function multiply():
def multiply(a, b):
return a * b
... then you can create a double() function1 with one of the arguments pre-filled like this:
from functools import partial
double = partial(multiply, 2)
... which works as expected:
>>> double(7)
14
1 Technically a partial object, not a function, but it behaves in the same way.
You can't have a multiline lambda expression in Python, but you can return a lambda or a full function:
def get_function1(x):
f = lambda y: x + y
return f
def get_function2(x):
def f(y):
return x + y
return f

lambda returns lambda in python

Very rarely I'll come across some code in python that uses an anonymous function which returns an anonymous function...?
Unfortunately I can't find an example on hand, but it usually takes the form like this:
g = lambda x,c: x**c lambda c: c+1
Why would someone do this? Maybe you can give an example that makes sense (I'm not sure the one I made makes any sense).
Edit: Here's an example:
swap = lambda a,x,y:(lambda f=a.__setitem__:(f(x,(a[x],a[y])),
f(y,a[x][0]),f(x,a[x][1])))()
You could use such a construct to do currying:
curry = lambda f, a: lambda x: f(a, x)
You might use it like:
>>> add = lambda x, y: x + y
>>> add5 = curry(add, 5)
>>> add5(3)
8
swap = lambda a,x,y:(lambda f=a.__setitem__:(f(x,(a[x],a[y])),
f(y,a[x][0]),f(x,a[x][1])))()
See the () at the end? The inner lambda isn't returned, its called.
The function does the equivalent of
def swap(a, x, y):
a[x] = (a[x], a[y])
a[y] = a[x][0]
a[x] = a[x][1]
But let's suppose that we want to do this in a lambda. We cannot use assignments in a lambda. However, we can call __setitem__ for the same effect.
def swap(a, x, y):
a.__setitem__(x, (a[x], a[y]))
a.__setitem__(y, a[x][0])
a.__setitem__(x, a[x][1])
But for a lambda, we can only have one expression. But since these are function calls we can wrap them up in a tuple
def swap(a, x, y):
(a.__setitem__(x, (a[x], a[y])),
a.__setitem__(y, a[x][0]),
a.__setitem__(x, a[x][1]))
However, all those __setitem__'s are getting me down, so let's factor them out:
def swap(a, x, y):
f = a.__setitem__
(f(x, (a[x], a[y])),
f(y, a[x][0]),
f(x, a[x][1]))
Dagnamit, I can't get away with adding another assignment! I know let's abuse default parameters.
def swap(a, x, y):
def inner(f = a.__setitem__):
(f(x, (a[x], a[y])),
f(y, a[x][0]),
f(x, a[x][1]))
inner()
Ok let's switch over to lambdas:
swap = lambda a, x, y: lambda f = a.__setitem__: (f(x, (a[x], a[y])), f(y, a[x][0]), f(x, a[x][1]))()
Which brings us back to the original expression (plus/minus typos)
All of this leads back to the question: Why?
The function should have been implemented as
def swap(a, x, y):
a[x],a[y] = a[y],a[x]
The original author went way out of his way to use a lambda rather then a function. It could be that he doesn't like nested function for some reason. I don't know. All I'll say is its bad code. (unless there is a mysterious justification for it.)
It can be useful for temporary placeholders. Suppose you have a decorator factory:
#call_logger(log_arguments=True, log_return=False)
def f(a, b):
pass
You can temporarily replace it with
call_logger = lambda *a, **kw: lambda f: f
It can also be useful if it indirectly returns a lambda:
import collections
collections.defaultdict(lambda: collections.defaultdict(lambda: collections.defaultdict(int)))
It's also useful for creating callable factories in the Python console.
And just because something is possible doesn't mean that you have to use it.
I did something like this just the other day to disable a test method in a unittest suite.
disable = lambda fn : lambda *args, **kwargs: None
#disable
test_method(self):
... test code that I wanted to disable ...
Easy to re-enable it later.
This can be used to pull out some common repetitive code (there are of course other ways to achieve this in python).
Maybe you're writing a a logger, and you need to prepend the level to the log string. You might write something like:
import sys
prefixer = lambda prefix: lambda message: sys.stderr.write(prefix + ":" + message + "\n")
log_error = prefixer("ERROR")
log_warning = prefixer("WARNING")
log_info = prefixer("INFO")
log_debug = prefixer("DEBUG")
log_info("An informative message")
log_error("Oh no, a fatal problem")
This program prints out
INFO:An informative message
ERROR:Oh no, a fatal problem
It is most oftenly - at least in code I come accross and that I myself write - used to "freeze" a variable with the value it has at the point the lambda function is created. Otherwise, nonlocals variable reference a variable in the scope they exist, which can lead to undesied results sometimes.
For example, if I want to create a list of ten functions, each one being a multiplier for a scalar from 0 to 9. One might be tempted to write it like this:
>>> a = [(lambda j: i * j) for i in range(10)]
>>> a[9](10)
90
Whoever, if you want to use any of the other factoried functions you get the same result:
>>> a[1](10)
90
That is because the "i" variable inside the lambda is not resolved when the lambda is created. Rather, Python keeps a reference to the "i" in the "for" statement - on the scope it was created (this reference is kept in the lambda function closure). When the lambda is executed, the variable is evaluated, and its value is the final one it had in that scope.
When one uses two nested lambdas like this:
>>> a = [(lambda k: (lambda j: k * j))(i) for i in range(10)]
The "i" variable is evaluated durint the execution of the "for" loop. ItÅ› value is passed to "k" - and "k" is used as the non-local variable in the multiplier function we are factoring out. For each value of i, there will be a different instance of the enclosing lambda function, and a different value for the "k" variable.
So, it is possible to achieve the original intent :
>>> a = [(lambda k: (lambda j: k * j))(i) for i in range(10)]
>>> a[1](10)
10
>>> a[9](10)
90
>>>
It can be used to achieve a more continuation/trampolining style of programming,
See Continuation-passing style
Basically, with this you can modify functions instead of values
One example I stumbled with recently: To compute approximate derivatives (as functions) and use it as an input function in another place.
dx = 1/10**6
ddx = lambda f: lambda x: (f(x + dx) - f(x))/dx
f = lambda x: foo(x)
newton_method(func=ddx(f), x0=1, n=10)

Categories