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.
Related
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?
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 am having trouble understanding the following function.
def make_adder(n):
return lambda x: x + n
plus_2 = make_adder(2)
plus_2(5)
>>> 7
In this function, what does x represent and how does this not result in an error because x is undefined?
The x represents the parameter that the lambda expression receives, this is why it's before the ":".
When you do the plus_2 = make_adder(2) call, the lambda expression substitutes the n with the parameter of the function (2), so now plus_2 equals lambda x: x + 2. When you call plus_2(5) the lambda expression is evaluated, substituting the x with the function parameter (5), so the result is 5 + 2 = 7;
You're defining a function which, given n, returns a function which accepts an argument x and returns x + n. This is called a higher-order function. It doesn't yield an error because you're explicitly returning another function which expects an argument.
Lambda functions are awesome. They allow you to define higher-order functions inline. The general format is lambda args: expression. In this case, x is the argument passed into the lambda function. Because make_adder returns a lambda function, whatever you pass into make_adder is set as n. So when you pass in make_adder(2) you get a lambda function that adds 2 to the argument (x).
Decomposing your original snippet:
def make_adder(n):
return lambda x: x + n
plus_2 = make_adder(2) # returns lambda x: x + 2
plus_2(5) # executes lambda expression, x + 2 with x=5
Starting from scratch:
5 + 2 # 7
plus_two_fn = lambda x: x + 2 # Add 2 when you call plus_two_fn(x)
plus_two_fn(3) # returns 5 (3 + 2)
def plus_num_fn(num):
return lambda x: x + n # Allow you to define plus "any" number
plus_one_fn = plus_num_fn(1) # lambda x: x + 1
plus_one_fn(2) # returns 3 (2 + 1)
In the line below:
plus_2 = make_adder(2)
we're binding the integer object 2 to n.
After that when plus_2 is called using the argument:
plus_2(5)
the integer object 5 would be bind to x when the lambda expression is executed.
This is the runtime execution flow. Since there is no ambiguity or errors in this whole process, the program runs just fine and outputs 7.
Now, to answer your question: the variable x represents whatever value is passed to plus_2() as per your naming.
I have come across this example from Python hitchhikers guide:
def create_multipliers():
return [lambda x, i=i : i * x for i in range(5)]
The example above is the solution to some issues caused with late binding, where variables used in closures are looked up at the time the inner function is called.
What does the i=i mean and why is it making such difference?
It's actually not just for lambdas; any function that takes default parameters will use the same syntax. For example
def my_range(start, end, increment=1):
ans = []
while start < end:
ans.append(start)
start += increment
return ans
(This is not actually how range works, I just thought it would be a simple example to understand). In this case, you can call my_range(5,10) and you will get [5,6,7,8,9]. But you can also call my_range(5,10,increment=2), which will give you [5, 7, 9].
You can get some surprising results with default arguments. As this excellent post describes, the argument is bound at function definition, not at function invocation as you might expect. That causes some strange behavior, but it actually helps us here. Consider the incorrect code provided in your link:
def create_multipliers():
return [lambda x : i * x for i in range(5)]
for multiplier in create_multipliers():
print multiplier(2)
When you call multiplier(2), what is it actually doing? It's taking your input parameter, 2, and returning i * 2. But what is i? The function doesn't have any variable called i in its own scope, so it checks the surrounding scope. In the surrounding scope, the value of i is just whatever value you left it -- in this case 4. So every function gives you 8.
On the other hand, if you provide a default parameter, the function has a variable called i in its own scope. What's the value of i? Well, you didn't provide one, so it uses its default value, which was bound when the function was defined. And when the function was defined, i had a different value for each of the functions in your list!
It is a bit confusing that they've used the same name for the parameter variable as they did for the iterating variable. I suspect you could get the same result with greater readability with
def create_multipliers():
return [(lambda x, y=i: y*x) for i in range(5)]
In that case, each number in the range, will be assigned to the optional parameters of each lambda function:
def create_multipliers():
return [lambda x, i=i : i * x for i in range(5)]
lambda x, i=0
lambda x, i=1
lambda x, i=2
lambda x, i=3
lambda x, i=4
So, you can call the functions now with one parameter (because they already have the default)
for f in create_multipliers():
print(f(3))
0
3
6
9
12
Or you can call the function and give the parameter you want, that's why is optional
for f in create_multipliers():
print(f(3,2))
6
6
6
6
6
There are examples where optional parameter are needed, such as recursion
For example, square in terms of square:
square = lambda n, m=0: 0 if n==m else n+square(n,m+1)
Look that the optional parameter there is used as accumulator
Title
I don't understand why the following code ignores the first function and run the second instead.
def f(x):
return 100
f = lambda x: 1 if x < 2 else x + f(x-1)
print(f(5))
the output is 15.
Thanks.
You define the first function as f. You immediately over-write that with a different function, calling that one f. This is just as if you'd run the code:
f = [1, 2, 3]
f = 7
print f
You will get only the 7; the list is lost.
The second definition of f overrides the first. Variables can't have two values. And function names are effectively just variables. When you assign to f, you overwrite the value of f, so the original function is no longer accessible.