CASE 1: ERROR output
def myfunc(n):
return lambda a : a * n
mytripler(11) = myfunc(3) => Error
===========================================
CASE 2: Correct output
def myfunc(n):
return lambda a : a * n
mytripler = myfunc(3)
print(mytripler(11))
How does the value 11 get passed to the method in the second case?
When myfunc is executed it is returning another function...
def myfunc(n):
Return lambda x : x*n
Is same as writing..
def myfunc(n):
def f(x):
Return x*n
return f
Hence in first function you are returning another function and as it has formed closure it has access to n variable of parent function.
It is because of the way lambda functions work, the value 11 is used in place of the variable 'a' in your case and n is already 3.
When mytripler = myfunc(3) is ran, it is returning a function(lambda) which looks like
def fun(a) :
return a * 3
Now the mytripler points to the above function "fun" which takes a single argument and multiplies it by 3.
Your function myfunc returns a function/callable (in this case lambda function), as can be seen here:
>>> def myfunc(n):
... return lambda a : a * n
>>> print(myfunc)
<function myfunc at 0x7efe15c9dea0>
Now, when we make the call to myfunc, the value passed as n will be bound in the lambda function:
>>> mytripler = myfunc(3)
>>> print(mytripler)
<function myfunc.<locals>.<lambda> at 0x7efe14f20598>
At this point mytripler is defined as lambda a : a * 3; the n was replaced by the value (or also: has been assgined the value) that we passed as argument to myfunc(). Note that this lambda construct is functionally equivalent to:
>>> def mytripler(a):
... return a * 3
Now, we can call mytripler with an value to make the final calculation/execution:
>>> mytripler(11)
33
Your error is that you cannot assign a value to a function call on the left-hand side:
>>> mytripler(11) = myfunc(3)
File "<input>", line 1
SyntaxError: can't assign to function call
But you can skip the intermediary step of assigning the result of myfunc to the name mytripler, and instead do both function calls chained together, like this:
>>> myfunc(3)(11)
33
Does that answer your question?
Related
How a function can be applied on top of another function like a(b)(x,y) where a and b are functions and x and y are arguments? Can somebody provide me with the term we call this concept along with some examples.
For a(b)(x, y) to make sense, a needs to be a function that takes b as an argument and produces a new function that takes two arguments. Here's an example:
>>> def a(func):
... def wrapped(x, y):
... return 2 * func(x, y)
... return wrapped
...
>>> def b(x, y):
... return x + y
...
>>> a(b)(1, 2)
6
In the above example a is a function that wraps a two-argument function and doubles its result. b(1, 2) is 3, and a(b)(1, 2) is therefore 6.
a function can be applied to another function like this
a(b)(x,y)
if the returned value from a(b) is a function that takes 2 arguments
in that case the function that is returned from a(b) will be applied on the parameters x,y
for example :
def mul(x,y):
return x*y
def add5_to_func(func):
return lambda x,y : func(x,y) + 5
print(add5_to_func(mul)(3,3)) # will print 14
Why in the following code, the output is 22?
In my understanding, we have a function that needs two arguments, but it has been defined with only one! However, the first time we use it in mydoubler = myfunc(2), it assigns the argument(2) to variable n, but the second time we use it in print(mydoubler(11), it uses the argument(11) to set the value of the variable a! Why is that? Does Lambda work like a recursive function?
def myfunc(n):
return lambda a : a * n
mydoubler = myfunc(2)
print(mydoubler(11))
Basically what happens is this:
mydoubler = myfunc(2) is actually the same as writing mydoubler = lambda a : a * 2
The reason for this is that myfunc(2) returns lambda a : a * 2
So now mydoubler = lambda a : a * 2
Then when mydoubler(11) is called, it simply returns 11 * 2
You're returning a lambda, which is a one-liner function, NOT a number. The code below does the EXACT SAME thing, but is maybe a bit clearer as to its purpose:
def multiplier_factory(constant_factor):
# Define our new function
def multiplier(factor):
result = constant_factor * factor
return result
# Return the FUNCTION, not a number
return multiplier
doubler = multiplier_factory(2)
tripler = multiplier_factory(3)
print (doubler(1)) # prints 2
print (tripler(1)) # prints 3
print (doubler('a')) # prints 'aa'
print (tripler('a')) # prints 'aaa'
lambda a: a * n is the same of:
def somefunction(a):
return a * n
When you called myfunc(2) you dynamically created a function that is the same of:
def somefunction(a):
return a * 2
myfunc returns a function. So mydoubler is a function and is described by lamda a : a * 2. Then you call that function with the argument 22 and so naturally 11 * 2 = 22 is printed. Lambda functions are not per se recursive, they are just a shorter way of writing a simple function. In your case you can also write:
def myfunc(n):
def multiplier(a):
return a * n
return multiplier
If I have a function that takes in a lambda reference as a parameter, and returns that reference so when it's called, it returns the value of that lambda function (boolean).
Is there a way to have it return the opposite boolean value?
def returns_diff(lambda_function):
return lambda_function
f = returns_diff(lambda x : x > 2)
f(0)
# I know I can do it this way but I want to do it inside the function.
# print(not(f(0)))
---> Should return True because it's supposed to return False since 0 is not bigger than two (return the opposite value of the lambda function)
I know I can just do: not(f(0)) when calling it, but I want to do it inside the function, not when I call it.
If you want to generate a function that returns the boolean opposite of a given function, you can do it like this:
def returns_diff(func):
return lambda x: not func(x)
f = returns_diff(lambda x: x>2)
f(0) # returns True
That's assuming the functions take one argument, as in your question. You can also make a version that works for functions with any number of positional or keyword arguments:
def returns_diff(func):
return lambda *args, **kwargs: not func(*args, **kwargs)
Can i use classes? Or it need to be just plain functions? With classes i would do
class diff:
def __init__(self,lambda_func):
self.lambda_func = lambda_func
def __call__(self,x):
return not(self.lambda_func(x))
f = diff(lambda x: x > 2)
f(0) #True
I don't understand how this lambda function knows x is equal to 1?
def one(f = None): return 1 if not f else f(1)
def two(f = None): return 2 if not f else f(2)
def plus(y): return lambda x: x+y
one(plus(two()))
3
I know that the inner function two() returns 2 because f is defaulted to None. Thus y= 2. But how does the lambda function know to look to the outmost function for the x value?
plus returns a (lambda) function. That function is passed to one. Within the scope of one, it is called f.
Then f (which is actually the lambda from returned from plus) is called in f(1).
In other words, the code one(plus(two())) does this:
number2 = two()
lambda_function = plus(number2)
result = one(lambda_function)
If you look at one() it passes "1" into a function which you pass in the arguments (if a function is passed. otherwise 1 is returned). Thus, it evaluates to f(1) (see in the else of one). The function you pass to one() is lambda x: x + 2 (since y=2). Thus, this evaluates to lambda 1: 1 + 2
If you call one(lambda x: 50), it returns 50.
Let's run through the steps first:
one gets a value, f, as plus(two()).
plus gets a value as two, two is gonna be 2 since no f.
Okay, so since one gets the value of that, it gonna condition and see that it shouldn't return 1, so does f(1) the f is the unfinished lambda process, the lambda needs one parameter more to add up, so it got 1, so 2 + 1 is 3.
That is the whole process really.
Could someone help explain what's going on here? I don't understand what is going on in the third part, and why the result is 9. Thank you!
>>> def square(x):
return x ** 2
>>> def f(x):
return x * x
>>> def try_f(f):
return f(3)
>>> try_f(square)
9
When calling try_f(square) you are passing the square function to try_f.
Inside try_f you named the first argument f: it will have nothing to do with the f() function defined below. This is now a local variable to the current scope of try_f.
As a better example, take this:
def square(x):
return x * x
def double(x):
return x * 2
def try_f(func):
return func(4)
>>> try_f(square)
16
>>> try_f(double)
8
The third function has a function as a parameter so when called it runs the parameter-function with a 3 as a paramater.
try_f(f=square) resolves as square(x=3) which resolves as x*x= 3*3 = 9
you call square function by parameter passing from try_f function and pass 3 as argument to it. You can add print to observe which function is called.
Defining f function doesn't take affect try_f behavour