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.
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.
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)
I am trying to define a function f() that will use a function g() n times - f(g(x), n) - to modify a single input. The thing is, I want to make it so that f(g(x), n) will output another function k(), such that k(a) will give me the final result. For example:
square = lambda x : x*x
test = f(square, 2)
test(2) = (2^2)^2 = 16
I have had many attempts, but most of the time a TypeError would occur.
Here is one of my attempts:
def square(x):
return x*x
def mainfunc(function, no_of_times):
def func(x):
if no_of_times == 0:
return x
else:
return function(mainfunc(function, no_of_times - 1))
return func
test = mainfunc(square, 2)
print(test(2))
Can I have some advice on whether I have had the correct approach? If not, what should I do?
Let's assume function and no_of_times are just global names. A function that applies function no_of_times times to a given value is easy to implement:
def func(x):
for _ in range(no_of_times):
x = function(x)
return x
But you want a function f that returns such a function. And also, function and no_of_times shall be parameters of f, not global variables. So simply wrap the func definition in the function f with the wanted signature and return the resulting inner function:
def f(function, no_of_times):
def func(x):
for _ in range(no_of_times):
x = function(x)
return x
return func
This works as wanted:
>>> f(lambda x: x*x, 2)(2)
16
>>> g = lambda x: x*x
>>> k = f(g, 2)
>>> k(2)
16
>>> g = lambda x: f'g({x})'
>>> k = f(g, 5)
>>> k('spam')
'g(g(g(g(g(spam)))))'
Implementing the inner function func in a functional style is left as an exercise to the reader. (And also wasn't what the question asked for.)
A few issues with your code:
You need to return 1 when you want to run the function zero times.
In the recursive part of mainfunc you use function(mainfunc(function, no_of_times - 1)). The use of the outer function is incorrect as you are calling your square function with a function object as its argument when it expects an int.That is why you get a TypeError: unsupported operand type(s) for *: 'function' and 'function'.
In the recursive part of the function you need square(x) * mainfunc(function, no_of_times - 1)(x).
Two points to note regarding point 3:
Your mainfunc returns func which expects an int as its argument. Thus, when you recurse you need to call it as follows: mainfunc(function, no_of_times - 1)(x).
Since you are now recursing no_of_times -1 you need to multiply by function(x) to ensure that your recursive function works as intended.
def square(x):
return x * x
def mainfunc(function, no_of_times):
def func(x):
if no_of_times == 0:
return 1
else:
return function(x) * mainfunc(function, no_of_times - 1)(x)
return func
test = mainfunc(square, 3)
print(test(3))
Output: 64
This does not work:
print((lambda : return None)())
But this does:
print((lambda : None)())
Why?
Because return is a statement. Lambdas can only contain expressions.
lambda functions automatically return an expression. They cannot contain statements. return None is a statement and therefore cannot work. None is an expression and therefore works.
Lambda can execute only expressions and return result of the executed statement, return is the statement.
Consider using or and and operators to short-circuit the result for more flexibility in the values which will be returned by your lambda. See some samples below:
# return result of function f if bool(f(x)) == True otherwise return g(x)
lambda x: f(x) or g(x)
# return result of function g if bool(f(x)) == True otherwise return f(x).
lambda x: f(x) and g(x)
because lambda takes a number of parameters and an expression combining these parameters, and creates a small function that returns the value of the expression.
see: https://docs.python.org/2/howto/functional.html?highlight=lambda#small-functions-and-the-lambda-expression
Remember a lambda can call another function which can in turn return anything (Even another lambda)
# Does what you are asking... but not very useful
return_none_lambda = lambda : return_none()
def return_none():
return None
# A more useful example that can return other lambdas to create multipier functions
multiply_by = lambda x : create_multiplier_lambda(x)
def create_multiplier_lambda(x):
return lambda y : x * y
a = multiply_by(4)
b = multiply_by(29)
print(a(2)) # prints 8
print(b(2)) # prints 58
I am using python so can someone tell me how to call same function twice in python but when you call it the second time it should be changed an already have value stored in it when you called the function the first time, so I basically mean you are calling the function first time and right after that you are calling it again but with the return value from the first time you called that function.
Assuming you have a function that has both a parameter and a return value:
def myFunction(input):
# do something with input
return input
To have a second instance of the function use the result of the first instance, you can simply nest the functions:
result = myFunction(myFunction(value))
you can create function that will apply n-times
def multf(f, n, x):
if n == 0:
return x
return multf(f, n-1, f(x))
so here we apply lambda sqr 3 times, it becomes f(f(f(x)))
sqr = lambda x: x**2
print(multf(sqr,3,2))
256