Reviewing the W3Schools Python tutorial, I am puzzled by their example of lambda.
Where on earth is the value for variable "a" coming from? Sure, "a" is the lambda - but where is it getting a value from?
def myfunc(n):
return lambda a : a * n
mytripler = myfunc(3)
print(mytripler(11))
If I call print(myfunc(3)) on it's own, I get an error. The function only works if the function is CALLED by another function. How does lambda a know any of this?
I fear I am missing something very fundamental about lambda functions.
Lambdas are just shorthands for full declarations. That makes your example functionally identical to this:
def myfunc(n):
def inner(a):
return a * n
return inner
The lambda is a function, and when you call it, you provide it an argument (a in this example).
What myfunc(3) does is that it assigns 3 to n and then this value is used in the lambda expression. So the expression becomes 3*a. Your lambda function has an independent variable a. When you return lambda a : a * n your mytripler is now acting as an object (function) whose argument is a and the action is to compute a*3. So finally when you call
mytripler(11)
you are assigning 11 to your independent variable a thereby getting 33
a in your example is assigned the value 11.
Think of the definition of a lambda function as "when given an input, return this". You can name the input anything, so let's call it x. lambda x : x + 1 means "given an input that we'll call x : return x + 1".
You have an extra layer of a function returning a lambda, but if we break it down, the purpose of myfunc is to dynamically generate a lambda function. When you call myfunc(3), what you now have in your hands is a lambda function that looks like this: lambda a : a * 3. This is what the variable mytripler contains. If you print(mytripler), you see something like this: <function myfunc.<locals>.<lambda> at 0x...>, which tells you that it's some lambda function. mytripler contains a function, not a value.
What does this lambda function do? It says "given one input parameter which we'll call a : return a * 3".
What do you do with functions? You call them! And send any parameters along with the call. How many parameters does our lambda function take? However many variables precede the colon in the lambda function definition, in this case one: a. And so we call the lambda stored in mytripler by sending it one parameter: mytripler(11). 11 is the input to the lambda function, which is first assigned to a and returns a * 3 -> 33.
You could have a lambda that takes 2 inputs that we'll call x and y:
adder = lambda x, y : x + y
What does this lambda do? It says "given 2 inputs that we'll call x and y : return their sum". How do you call it? You have to call adder with two parameters: adder(2,3) returns 5. 2 is assigned to x, 3 is assigned to y and the function returns their sum.
What if we call adder(1)?
TypeError: <lambda>() missing 1 required positional argument: 'y'
From this you can see that Python knows how many input parameters the lambda function expects from its definition and cannot work without first getting all the parameters it needs.
Related
I need to write a python function called 'concat' that takes any two functions as input, and returns a function, which is the concatenated function of the two input functions (i.e. it takes f1 and f2, and returns f1◦f2).
I tried this:
def concat(f1,f2):
return f1(f2)
So for example, if f1 and f2 are:
def f1(x):
return x+2
def f2(x):
return x*2
then, concat(f1,f2) should return: (x*2)+2
I want to be able to use it like this:
a = concat(f1,f2)
a(5)
But I get an error:
TypeError: unsupported operand type(s) for +: 'function' and 'int'
I know I can define the function like this:
def concat(f1,f2,x):
return f1(f2(x))
But that is not what I want; I want to be able to create instances of the concat function, which then can be called with any x.
You need to return a new "wrapper" function. One option is to use a lambda expression:
def concat(f1, f2):
return lambda x: f1(f2(x))
DOCS: https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions
I think what you want is a closure.
def concat(f1, f2):
def f3(x):
return f1(f2(x))
return f3
Functions in Python are considered first class objects. This allows them to be created and manipulated like normal variables. In this case concat is constructing a new function that composes two functions.
The second property being used here is lexical scoping. The new function retains access to the local variables where it was defined not where it is executed. This allows the returned function to be run anywhere without losing access to the composite functions.
Here's a possible solution to compose more than two functions. Using a closure to loop through the functions and use the previous function's result as argument for the next one:
def compose(*fns):
def F(x):
for fn in fns[::-1]:
x = fn(x)
return x
return F
Then define your composition and call:
>>> F = compose(f1, f2, lambda x: x+1)
>>> F(4)
12 # f1(f2(f3(x)))
I don't understand how the mydoubler object which references the function myfunc is passing a parameter to 'a' inside the lambda expression.
What I do get is this:
There is a function 'myfunc' that takes a parameter 'n'. The function 'myfunc' returns a value using a lambda expression 'lambda a : a * n'.
The object mydouble is a reference to the function 'myfunc(2)' where mydoubler is 'return lambda a : a * 2'.
Does the reference also mean that 'mydoubler' acts just like myfunc(n) and therefore takes a parameter where that parameter must be the only other variable inside the function 'myfunc'. Such that mydoubler(a) really is:
'return lambda a : a * 2
def myfunc(n):
return lambda a : a * n
mydoubler = myfunc(2)
print(mydoubler(11))
No errors are returned, just me trying to understand what is happening.
lambda function is a small anonymous function
A lambda function can take any number of arguments, but can only have one expression
the lambda function works as follows
lambda (args):return value
so basically its like any other function
consider the following example
x = lambda a, b : a * b
print(x(5, 6))
x now is like a function (function inside variable) such that you can call it whenever you want
...it takes a,b as parameters and returns a*b, so in this case the result would be 30
in your case you've lambda anonymous function inside python function, so what happen is
you call myfunc passing n value it goes to lambda function and the function is returned (note that the lambda function is returned) you call the lambda function again with the given value and it return the result
I am trying to write some code that will send the value of an Entry box to a function based on a binding. I can technically get the behavior I want in the code below, but I'm a) not sure why it works and b) am quite sure I am not doing this in the most pythonic way. I'm pretty sure I'm misunderstanding the event or lambda or both.
In the code below the Entry box called input_box1 when the binding triggers, the inp_var1.get() code only gets the default value, not anything that has been entered into the box. In other words, the test1 function will print...
Test1 Foo
... no matter what you type into the entry.
The binding on input_box2 works exactly as I expect. I type anything in there and click somewhere else and it prints the new entry. However I don't understand why my lambda doesn't want an event or why I need to repeat the inp_var2.get() call.
If anyone knows what's going under the hood I'd love to hear it! Here's the code:
from tkinter import *
from tkinter import ttk
def test1(event, i):
print('Test1', i)
def test2(event, i):
print('Test2', i)
root = Tk()
title_label = Label(root, text='This does not work!')
title_label.grid(column=0, row=0)
inp_var1 = StringVar(value='Foo')
input_box1 = Entry(root, textvariable=inp_var1)
input_box1.grid(column=0, row=1)
inp_var2 = StringVar(value='Bar')
input_box2 = Entry(root, textvariable=inp_var2)
input_box2.grid(column=0, row=2)
input_box1.bind('<FocusOut>', lambda event, i=inp_var1.get(): test1(event, i))
input_box2.bind('<FocusOut>', lambda i=inp_var2.get(): test2(i, inp_var2.get()))
root.mainloop()
This has very little to do with Tkinter itself. It's also not so much connected to lambda as it is to Python in general.
Take both of those out of the equation, and consider the following Python program:
def f(x=3, y=4):
print('x =', x, 'y =', y)
f(0, 0)
f(0)
f()
Assuming Python 3 (or from __future__ import print_function), when run, this prints:
x = 0 y = 0
x = 0 y = 4
x = 3 y = 4
That's because the first call to f passes 0, 0, so x and y are both bound to zero. The second call to f passes just 0 so x is bound to 0 and y is bound to its default value of 4. The third call passes nothing at all and x and y are both bound to their default values.
(So far, this should all be clear enough.)
Now let's fuss with this a bit. I'll continue to assume Python 3 so that input means what in Python 2 we have to use raw_input to achieve:
def f(x=input('enter default x: '), y=input('enter default y: ')):
print('x =', x, 'y =', y)
print('about to call f three times')
f(0, 0)
f(0)
f()
Before you run this sample program, think about what you expect it to do. Then run it—here's my result:
$ python3 t.py
enter default x: hello
enter default y: world
about to call f three times
x = 0 y = 0
x = 0 y = world
x = hello y = world
Why did this read the default values for x and y before we even called it the first time? Why didn't it read new default values for x and y on each call?
Think about that for a bit, then read on
Really, do that. Ask why the inputs happened at these odd times.
Now that you've thought about it...
It did do that, though. That's the key here. The default values for your arguments are captured at the time the def statement is executed. The def statement, which binds the name f to our function, is actually run when Python loads the file, after seeing the body of the function. The function itself is run later, after Python has gotten to the print call and then to the first f call.
A lambda in Python is just a sort of anonymous function definition. Instead of:
def square(x):
return x * x
we can write:
square = lambda x: x * x
The lambda expression defines a new function-like item, a lambda function—you can't use if/else type statements inside one of these, just expressions, and they automatically return the value of their expression. In this case our lambda function has one argument named x. The function returns x * x.
The outer assignment, square =, binds this lambda function to the name square, just as if we'd done def square(x) instead. So it's mostly just a syntactic trick: we can have a real function, like square, with arguments, or a limited lambda function that can only use expressions, like this anonymous function that we almost immediately bind to the name square.
The arguments part works the same either way though. Just as with f and input, if we bind x:
square = lambda x=3: x * x
or:
square = lambda x=int(input('choose a default for x now> ')): x * x
that happens just once, when the lambda expression itself executes. The function now has a variable x with a default value.
When, later, we call the function, we can provide a value for x, or let it default. If we don't provide a value, Python uses the default that it captured earlier, when we executed the line with lambda in it, rather than now, when we call the lambda function.
This all holds for Tkinter as well. You wrote:
input_box2.bind('<FocusOut>', lambda i=inp_var2.get(): test2(i, inp_var2.get()))
but that's pretty much the same as writing:
def f(i=inp_var2.get()):
test2(i, inp_var2.get())
input_box2.bind('<FocusOut>', f)
except that you don't have to come up with the function-name f here. The lambda variant of the function has no name, but it's still just a function. (For that matter, when we do square = lambda ..., the lambda function doesn't have a name. The name square is the name of a variable, not the name of the function. The variable is merely bound to the function, so that square(10) calls it.)
Anyway, later, when Tkinter has an event that matches <FocusOut>, Tkinter calls f ... or, if you used lambda, calls your unnamed lambda function. Tkinter provides one argument to that function; the one argument it provides is the event. So your default value for i in f above is irrelevant—you could do:
def f(i=None):
test2(i, inp_var2.get())
or:
def f(i='hello world'):
test2(i, inp_var2.get())
because when Tkinter calls f, it always provides an actual argument for i.
def apply_twice(func,arg):
return func(func(arg))
def add_five(x):
return x+5
print (apply_twice(add_five,10))
The output I get is 20.
This one is actually confusing me like how is it working.Can anybody explain me how this is working by breaking it down
The function apply_twice(func,arg) takes two arguments, a function object func and an argument to pass to the function func called arg.
In Python, functions can easily be passed around to other functions as arguments, they are not treated differently than any other argument type (i.e first class citizens).
Inside apply_twice, func is called twice in the line:
func(func(arg))
Which, alternatively, can be viewed in a more friendly way as:
res = func(arg)
func(res)
If you replace func with the name of the function passed in add_five you get the following:
res = add_five(arg) # equals: 15
add_five(res) # result: 20
which, of course, returns your expected result.
The key point to remember from this is that you shouldn't think of functions in Python as some special construct, functions are objects just like ints, listss and everything else is.
Expanding the code it executes as follows, starting with the print call:
apply_twice(add_five,10))
add_five(add_five(10)) # add_five(10) = 15
add_five(15) # add_five(15) = 20
Which gives you the result: 20.
When apply_twice is called, you are passing in a function object and a value. As you can see in the apply_twice definition, where you see func that is substituted with the function object passed to it (in this case, add_five). Then, starting with the inner func(arg) call, evaluate the result, which is then passed to add_five again, in the outer return func( ... ) call.
What you need to understand here is that
apply_twice(func,arg)
is a higher function which accepts two arguments (another function named func and an argument arg). The way it works is that it first evaluate the value of the other function, then use the value as an argument inside the higher function.
remember we have a function add_five(x) which add 5 to the argument supply in it...
then this function add_five(x) is then passed as an argument to another function called
apply_twice_(func,arg) which return func(func(arg)).
now splitting func(func(arg)) we have
func(arg) #lets called it a
then func(func(arg))==func(a) since a = func(agr)
and (a) is our add_five(x) function, after it add 5, then the value we got is re-used as another fresh argument to add another 5 to it, that is why we have 20 as our result.
Another example is:
def test(func, arg):
return func(func(arg))
def mult(x):
return x * x
print(test(mult, 2))
which give 16 as result.
What does the following code do?
a = lambda _:True
From what I read and tested in the interactive prompt, it seems to be a function that returns always True.
Am I understanding this correctly? I hope to understand why an underscore (_) was used as well.
The _ is variable name. Try it.
(This variable name is usually a name for an ignored variable. A placeholder so to speak.)
Python:
>>> l = lambda _: True
>>> l()
<lambda>() missing 1 required positional argument: '_'
>>> l("foo")
True
So this lambda does require one argument. If you want a lambda with no argument that always returns True, do this:
>>> m = lambda: True
>>> m()
True
Underscore is a Python convention to name an unused variable (e.g. static analysis tools does not report it as unused variable). In your case lambda argument is unused, but created object is single-argument function which always returns True. So your lambda is somewhat analogous to Constant Function in math.
it seems to be a function that returns True regardless.
Yes, it is a function (or lambda) that returns True. The underscore, which is usually a placeholder for an ignored variable, is unnecessary in this case.
An example use case for such a function (that does almost nothing):
dd = collections.defaultdict(lambda: True)
When used as the argument to a defaultdict, you can have True as a general default value.
Below is the line of code in question:
a = lambda _:True
It creates a function having one input parameter: _. Underscore is a rather strange choice of variable name, but it is just a variable name. You can use _ anywhere, even when not using lambda functions. For example, instead of....
my_var = 5
print(my_var)
You could write:
_ = 5
print(_)
However, there was a reason that _ was used as the name of parameter name instead of something like x or input. We'll get to that in a moment.
First, we need to know that the lambda-keyword constructs a function, similar to def, but with different syntax. The definition of the lambda function, a = lambda _:True, is similar to writing:
def a(_):
return True
It creates a function named a with an input parameter _, and it returns True. One could have just as easily written a = lambda x:True, with an x instead of an underscore. However, the convention is to use _ as a variable name when we do not intend to use that variable. Consider the following:
for _ in range(1, 11):
print('pear')
Notice that the loop index is never used inside of the loop-body. We simply want the loop to execute a specified number of times. As winklerrr has written, "the variable name _ is [...] like a "throw-away-variable", just a placeholder which is of no use. "
Likewise, with ``a = lambda x:True the input parameter is not used inside the body of the function. It does not really matter what the input argument is, as long as there is one. The author of that lambda-function wrote _ instead of something like x, to indicate that the variable would not be used.
Note that the lambda does have an argument; So, writing
a(), will raise an error.
If you want a lambda with no argument write something like this:
bar = lambda: True
Now calling bar(), with no args, will work just fine.
A lambda which takes no arguments need not always return the same value:
import random
process_fruit = lambda : random.random()
The lambda function above is more complex that just a something which always returns the same constant.
One reason that programmers sometimes us the lambda keyword instead of def is for functions which are especially short and simple. Note that a lambda definition can usually fit all on one line, whereas, it is difficult to do the same with a def statement. Another reason to use lambda instead of def sf when the function will not be used again. If we don't want to call the function again later, then there is no need to give the function a name. For example consider the following code:
def apply_to_each(transform, in_container):
out_container = list()
for idx, item in enumerate(container, 0):
out_container[idx] = transform(item)
return out_container
Now we make the following call:
squares = apply_to_each(lambda x: x**2 range(0, 101))
Notice that lambda x: x**2 is not given a label. This is because we probably won't call it again later, it was just something short and simple we needed temporarily.
The fact that lambda functions need not be given a name is the source of another name to describe them: "anonymous functions."
Also note that lambda-statements are like a function-call in that they return a reference to the function they create. The following is illegal:
apply_to_each(def foo(x): x**2 , range(0, 101))
Whereas, apply_to_each(lambda x: x**2 range(0, 101)) is just fine.
So, we use lambda instead of def and _ instead of a long variable name when we want something short, sweet and probably won't want use again later.
Lambda means a function.
The above statement is same as writing
def f(_):
return True
For lambda a variable needs to be present. So you pass it a variable called _(Similarly you could pass x, y..)
Underscore _ is a valid identifier and is used here as a variable name. It will always return True for the argument passed to the function.
>>>a('123')
True