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)
Related
I am trying to double numbers using Lambda function in python but can't understand the function that's all because I'm starting to learn python. Below is the function:
def myfunc(n):
return lambda a : a * n
mydoubler = myfunc(2)
print(mydoubler(11))
I just need to understand how this code is working. Any help will be much appreciated.
def myfunc(n): # this function is taking input n and returning a function object
return lambda a : a * n # this function is taking input as a and we are returning this function object
mydoubler = myfunc(2) # now we are calling the returned function object if you print(mydoubler)-> this will give you function object
print(mydoubler(11)) # here we are calling the lambda function with parameters
If you want to implement it without lambda then you can use partial
from functools import partial
def double(n, a):
return a * n
def my_func1(n):
return partial(double,n)
mydoubler = my_func1(2)
print(mydoubler(11))
Your myfunc function creates and returns a closure. In this case, it returns a function that returns its argument times n. The tricky part is that n refers to the value in the specific call frame for myfunc. In your example, n has the value 2. That instance of n is specific to that particular call to myfunc. So if you called myfunc several times in a row, with several different values for n, each of the returned lambda functions would refer to a unique value of n unrelated to the other values.
Note that the use of lambda is optional. It's just shorthand for an anonymous function. For example, you could have written myfunc as:
def myfunc(n):
def f(a):
return a * n
return f
which would produce the same result.
Back to the original question, here's an example of multiple closures coexisting:
def myfunc(n):
def f(a):
return a * n
return f
mydoubler = myfunc(2)
mytripler = myfunc(3)
print(mydoubler(11))
print(mytripler(11))
This prints 22 followed by 33. This works because mydoubler and mytripler each refer to different instances of n.
The value of n can even be modified by calls to the returned closure. For example:
def myfunc(n):
def f(a):
nonlocal n
n += a
return n
return f
func = myfunc(100)
print(func(1))
print(func(5))
This prints 101 followed by 106. In this example, the nonlocal declaration is needed since f assigns to n. Without it, n would be taken to be local to f.
def myfunc(n):
return lambda a : a * n
mydoubler = myfunc(2)
print(mydoubler(11))
The value of n = 2, after that I'm confused what is the value of a, and how the lambda function is executed.
Your myfunc is a nested function, lambdas are functions.
An equal implementation would be:
def outer(n):
def inner(a):
return a * n
return inner
Which returns a function like your original myfunc as well. Since the return of the call of myfunc is also a function, you may well call the inner function as well.
When the outer function is called, the inner lambda creates a function. The outer lambda then returns the called function.It happens that describe above..i.e: when we call mydoubler(11),given the value a=11 and call n=2.
I am following the Python tutorial.
def make_incrementor(n):
return lambda x: x + n
Result:
f = make_incrementor(42)
print(f(1))
43
print(type(f))
<class 'function'>
Now consider we will replace the lambda expression by a regular function
def nolambda(x):
return x
def make_incrementor(n):
return nolambda(n)
f = make_incrementor(42)
print(type(f))
<class 'int'>
In the first case it returned <class 'function'> but in the second it returned <class 'int'>
It only points to the lamba expression in the first case and do not execute it (ok, it would raise an error because of the missing argument). I could understand that but it returns an int rather than a function in the second example, so it is very strange to me. Could you explain what's going on?
In the first example, you are returning a callable (ie. the lambda function).
In the second example, you are calling the nolambda function, which means that the return value of make_incrementor will be the same value returned by nolambda.
To better understand, try looking at it like this:
def make_incrementor(n):
def some_function(x):
return x + n
return some_function
def make_incrementor(n):
some_return_value = nolambda(n)
return some_return_value
In this code, the lambda function "sees" the argument x and the variable n, which is in the lambda's closure:
def make_incrementor(n):
return lambda x: x + n
In the other example, you have made three differences, which cause different behaviour:
you placed the function nolambda outside the make_incrementor function, so it does not have the closure
in the first example, you return the function itself (i.e. the lambda, which is a function), and in the second you return the result of nolambda
the lambda returns x + n, whereas the nolambda returns just x
The following would be equivalent to the example with lambda:
def make_incrementor(n):
def nolambda(x):
return x + n
return nolambda
In the first example, where you return lambda x: x + n, you're returning a callable (i.e. anonymous function) without an invocation – the callable maps the input parameter, n, to the lambda function but does not actually get invoked. In the second, you are returning the invoked function, because you're actually calling it by using parentheses within the make_incrementor function's body.
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.
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