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.
Related
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)
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 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
The below assignment is taken from here:
Q5. Define the repeated function from Homework 2 by calling reduce with compose1 as the first argument. Add only a single expression to the starter implementation below:
def square(x):
return x*x
def compose1(f, g):
"""Return a function of x that computes f(g(x))."""
return lambda x: f(g(x))
from functools import reduce
def repeated(f, n):
"""Return the function that computes the nth application of f, for n>=1.
f -- a function that takes one argument
n -- a positive integer
>>> repeated(square, 2)(5)
625
>>> repeated(square, 4)(5)
152587890625
"""
assert type(n) == int and n > 0, "Bad n"
return reduce(compose1, "*** YOUR CODE HERE ***" )
To complete this assignment, I would like to understand, to what does g bind to? f binds to the square function.
First, what should repeated(f, 4) return?
A function that, when called on some arbitrary arg, will return f(f(f(f(arg)))).
So, if you want to build that with compose1, you'll need to return either compose1(compose1(compose1(f, f), f), f) or compose1(f, compose1(f, compose1(f, f))).
Now, look at what reduce does, and figure out what it's going to pass to compose1 each time. Clearly your iterable argument has to either start or end with f itself. But what else do you want there to make sure you get one of the two acceptable results?
And meanwhile, inside each call to compose1 except the last, one of the two arguments has to be the repeated function's f, while the other will be the result of another call to compose1. (The last time, of course, they'll both be f.) Figure out which of those is f and which is g, and how you get reduce to pass the right values for each, and you've solved the problem.
I wanted to learn about using map in python and a google search brought me to http://www.bogotobogo.com/python/python_fncs_map_filter_reduce.php which I have found helpful.
One of the codes on that page uses a for loop and puts map within that for loop in an interesting way, and the list used within the map function actually takes a list of 2 functions. Here is the code:
def square(x):
return (x**2)
def cube(x):
return (x**3)
funcs = [square, cube]
for r in range(5):
value = map(lambda x: x(r), funcs)
print value
output:
[0, 0]
[1, 1]
[4, 8]
[9, 27]
[16, 64]
So, at this point in that tutorial, I thought "well if you can write that code with a function on the fly (lambda), then it could be written using a standard function using def". So I changed the code to this:
def square(x):
return (x**2)
def cube(x):
return (x**3)
def test(x):
return x(r)
funcs = [square, cube]
for r in range(5):
value = map(test, funcs)
print value
I got the same output as the first piece of code, but it bothered me that variable r was taken from the global namespace and that the code is not tight functional programming. And there is where I got tripped up. Here is my code:
def square(x):
return (x**2)
def cube(x):
return (x**3)
def power(x):
return x(r)
def main():
funcs = [square, cube]
for r in range(5):
value = map(power, funcs)
print value
if __name__ == "__main__":
main()
I have played around with this code, but the issue is with passing into the function def power(x). I have tried numerous ways of trying to pass into this function, but lambda has the ability to automatically assign x variable to each iteration of the list funcs.
Is there a way to do this by using a standard def function, or is it not possible and only lambda can be used? Since I am learning python and this is my first language, I am trying to understand what's going on here.
You could nest the power() function in the main() function:
def main():
def power(x):
return x(r)
funcs = [square, cube]
for r in range(5):
value = map(power, funcs)
print value
so that r is now taken from the surrounding scope again, but is not a global. Instead it is a closure variable instead.
However, using a lambda is just another way to inject r from the surrounding scope here and passing it into the power() function:
def power(r, x):
return x(r)
def main():
funcs = [square, cube]
for r in range(5):
value = map(lambda x: power(r, x), funcs)
print value
Here r is still a non-local, taken from the parent scope!
You could create the lambda with r being a default value for a second argument:
def power(r, x):
return x(r)
def main():
funcs = [square, cube]
for r in range(5):
value = map(lambda x, r=r: power(r, x), funcs)
print value
Now r is passed in as a default value instead, so it was taken as a local. But for the purposes of your map() that doesn't actually make a difference here.
Currying is another option. Because a function of two arguments is the same as a function of one argument that returns another function that takes the remaining argument, you can write it like this:
def square(x):
return (x**2)
def cube(x):
return (x**3)
def power(r):
return lambda(x): x(r) # This is where we construct our curried function
def main():
funcs = [square, cube]
for y in range(5):
value = map(power(y), funcs) # Here, we apply the first function
# to get at the second function (which
# was constructed with the lambda above).
print value
if __name__ == "__main__":
main()
To make the relation a little more explicit, a function of the type (a, b) -> c (a function that takes an argument of type a and an argument of type b and returns a value of type c) is equivalent to a function of type a -> (b -> c).
Extra stuff about the equivalence
If you want to get a little deeper into the math behind this equivalence, you can see this relationship using a bit of algebra. Viewing these types as algebraic data types, we can translate any function a -> b to ba and any pair (a, b) to a * b. Sometimes function types are called "exponentials" and pair types are called "product types" because of this connection. From here, we can see that
c(a * b) = (cb)a
and so,
(a, b) -> c ~= a -> (b -> c)
Why not simply pass the functions as part of the argument to power(), and use itertools.product to create the required (value, func) combinations?
from itertools import product
# ...
def power((value, func)):
return func(value)
for r in range(5):
values = map(power, product([r], funcs))
print values
Or if you don't want / require the results to be grouped by functions, and instead want a flat list, you could simply do:
values = map(power, product(range(5), funcs))
print values
Note: The signature power((value, func)) defines power() to accept a single 2-tuple argument that is automatically unpacked into value and func.
It's equivalent to
def power(arg):
value, func = arg