What exactly is the difference between 'Lambda formats'? - python

First of all, I'm a begginer in Python, so get ready for a nooby question ))
In one of the topics on this site I've found quite a useful piece of advice concerning the use of lambda function.
Here's my code before correcting:
def entree1(self): #function that is supposed to change text in
self.configure(text = "X") the label block from whatever it is to 'X'
fen = Tk()
pole1 = Label(fen, text = '|_|')
pole1.bind("<Button-1>", lambda: entree1(pole1)) #event handler reffering to the function above
Here's my code after correcting:
def entree1(self): #function that is supposed to change text in
self.configure(text = "X") the label block from whatever it is to 'X'
fen = Tk()
pole1 = Label(fen, text = '|_|')
pole1.bind("<Button-1>", lambda x: entree1(pole1)) #event handler reffering to the function above
In a nutshell I changed lambda: some func to lambda x: some func.
And it worked, which is great, although I can't figure out the difference between this two variants.
Could you please tell me what exactly changed after I added x?
Thank you for your time!

Let me translate lambda expressions to function definitions that you are probably more used to:
lambda : entree1(pole1)
is the same as
def lambdaFunc():
global pole1
return entree1(pole1)
Your corrected function is
lambda x : entree1(pole1)
which is the same as
def lambdaFunc(x):
global pole1
return entree1(pole1)
You need the extra argument because Tk buttons call the function they are bound to with a variable (I forget what the variable is, exactly), therefore calling a function with an input variable when it doesn't take one causes errors.

Related

When defining a lambda function with a variable inside, how to prevent changes in function when I change the variable?

For example: in this code, function changes when the variable changes. I would like to learn how to prevent the change in function behaviour when i change the variable. Is there some way to only get the value of the variable instead of the variable itself? Also are there any sources where I can learn more about problems like this?
a = 5
adder = lambda x: x + a
print(adder(5)) # prints 10
a = 50
print(adder(5)) # prints 55
Just like the equivalent function defined by a def statement (which is what you should be using, rather than assigning the result of a lambda expression to a name explicitly)
def adder(x):
return x + a
the name a isn't looked up until the function is called.
One way to make a function that specifically computes x + 5 when a == 5 at definition time is use a default argument value:
def adder(x, a=a):
return x + a
where the left-hand a is a new parameter (which isn't intended to be set explicitly), and the right-hand a is the value of the a in the current scope.
A better idea, though, is to define a closure, so that your function doesn't have a "hidden" parameter that can be abused.
# This is where a lambda expression does make sense: you want
# a function, but don't need to give it a name.
def make_adder(a):
return lambda x: x + a
adder = make_adder(5)
a in adder is still a free variable, but now it refers to a variable in a scope which you don't "outside" access to after make_adder returns.

How is Tkinter handling lambda after binding event?

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.

How to complete this function then print it out, using Python?

I'm having a hard time to understand how to work with functions - I can make then but after that I don't know how to use them. My question is how can I print this code with a function?
string = "Hello"
reverse = string[::-1]
print(reverse)
I tried putting it in a function but I cannot make it print Hello.
def reverse_a_string(string):
string = "Hello"
reverse = string[::-1]
print(reverse)
also tried this
def reverse_a_string(string):
string = "Hello"
reverse = string[::-1]
print(reverse)
Nothing seems to work. I'm having same problem with this as well.
total = 0
def length(words):
for i in words:
total += 1
return total
Functions without a return value
Functions that just take action or do something without returning a value (for example, print).
Functions that don't return a value can be defined like that:
def sayHello():
print "Hello!"
And can be used (called) like that:
sayHello()
And the output will be:
Hello!
Function parameters
A function can also receive parameters (type of variables) from the caller. It's better to demonstrate it with an example.
A function that receives a name and greets this name:
def sayHelloTo(name):
print "Hello", name
It can be called like that:
sayHelloTo("Yotam")
And the output will be:
Hello Yotam
The parameters are the function's input.
Functions with a return value
Other functions, unlike sayHello() or sayHelloTo(name) (that just do something) can return a value. For example, let's make a function that rolls a dice (returns a random number between 1 and 6).
from random import randint
def rollDice():
result = randint(1, 6)
return result
The return keyword just sets the output value of the function and exits the function. An example use of the rollDice function will be:
dice = rollDice()
print "The dice says", dice
When the function hits a return keyword, it finishes and the return value (in our case, the variable result) will be placed instead of the function call. Let's assume randint(1, 6) has produced the number 3.
Result becomes 3.
Result is returned.
Now, instead of the line:
dice = rollDice()
We can treat the line as:
dice = 3
(rollDice() was replaced with 3)
Functions with parameters and a return value
Some functions (for example, math functions) can take inputs AND produce outputs. For example, let's make a function that receives 2 numbers and outputs the greater one.
def max(a,b):
if a > b:
return a
else:
return b
What it does is pretty clear, isn't it? If a is greater, it returns the value of it. Otherwise, returns the value of b.
It can be used like that:
print max(4, 6)
And the output will be:
6
Now, your case
What you want to do is a function that reverses a string. It should take 1 parameter (input) - the string you want to reverse, and output 1 value - the reversed string. This can be accomplished like that:
def reverse_a_string(my_text):
return my_text[::-1]
now you can do something like that:
s = raw_input("Please enter a string to be reversed\n") #input in Python3
r = reverse_a_string(s)
print r
r will contain the reversed value of s, and will be printed.
About your second function - well, I assume that based on this answer you can make it yourself, but comment me if you need assistance with the second one.
Local variables
About your 3rd example:
def reverse_a_string(string):
string = "Hello"
reverse = string[::-1]
print(reverse)
This is something that is really worth delaying and understanding.
the variable reverse is first used inside the function. This makes it a local variable.
This means that the variable is stored in the memory when the function is called, and when it finishes, it is removed. You can say it's lifetime is from when the function is called to when the function is done.
This means that even if you called reverse_a_string(string), you wouln't be able to use the reverse variable outside of the function, because it would be local.
If you do want to pass a value like that, you have to "declare" your variable outside of the function and to use the global keyword, like that:
reverse = "" #This makes reverse a global variable
def reverse_a_string(string):
global reverse #Stating that we are going to use the global variable reverse
reverse = string[::-1]
# Then you can call it like that:
reverse_a_string("Hello")
print reverse
The output will be
olleH
Although it's strongly not recommended to do it in Python, or in any other language.
Once you create a function you must call it. You have created the function reverse_a_string but then you never actually call it. Think about a function as a button that does something everytime it is pushed (or in our case called). If you never push the button then although it has the potential to do something, it never will. In order for the set of instructions to happen we need to push the button (or in our case call the function). So in order for your code to work you first need to define the function then actually call it:
def reverse_a_string():
string="Hello"
reverse = string[::-1]
print reverse
reverse_a_string()
Result: 'olleH'
If you want to pass your own string in to the function so it doesn't just return 'olleH' all the time your code needs to look like such:
def reverse_a_string(stringThatWillBeReversed):
reverse = stringThatWillBeReversed[::-1]
print reverse
reverse_a_string('whateverStringYouWant')
Result: The reverse of the string you entered.
Hope that helps!
I don't know whether you are asking how to define functions in python or something else
If you want to learn python functions, go to http://www.tutorialspoint.com/python/python_functions.htm or just write python tutorial in google, you will get billions of good sites
def reverse_a_string(string):
#function definition
reverse = string[::-1]
print(reverse)
#function call
reverse_a_string("your string")
But you to define function for this, you could simply do
print( string[::-1] )
# defines the 'Reverse a String' function and its arguments
def reverse_a_string():
print(string)
reverse = string[::-1]
print(reverse)
print("Type a string") # asks the user for a string input
string = input() # assigns whatever the user input to the string variable
reverse_a_string() # simply calls the function
for functions, you have to define the function, then simply call it with the function name i.e. funtion()
In my example, I ask for a string, assign that to the variable, and use it within the function. If you just want to print hello (I'm a little unclear from your question) then simply including the print("hello") or w/ variable print(string) will work inside the function as well.

Python's lambda with underscore for an argument?

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

Python Tkinter button callback

I am trying to print out the button number when i click each buttons that are created by for loop. The following is what i have tried.
import Tkinter as tk
root=tk.Tk()
def myfunction(a):
print a
for i in range(10):
tk.Button(root,text='button'+str(i),command=lambda:myfunction(i)).place(x=10,y=(10+(25*i)))
root.mainloop()
But instead of printing out each button number, it actually giving me the last button number everytime. Is there anything i can do so that when i click button 1, it will print 1,2 for 2 ,and so on?
Easy fix is to initialize the lambda function with the current value of i each time the lambda function is created. This can be done using Python default values for another dummy variable j.
command = lambda j=i: myfunction(j)
Blender's answer is a clever solution but in case you get thrown off by the function abstraction, here is another possible way to do it. It really just creates a mapping, saved in buttons, from Button widgets to their proper numbers.
import Tkinter as tk
root = tk.Tk()
def myfunction(event):
print buttons[event.widget]
buttons = {}
for i in range(10):
b = tk.Button(root, text='button' + str(i))
buttons[b] = i # save button, index as key-value pair
b.bind("<Button-1>", myfunction)
b.place(x=10,y=(10+(25*i)))
root.mainloop()
The problem is that the Button command in tk ignores any parameters so insomething like mycommand(data) the data is ignored.
I use buttons quite a bit and decided to subclass a tk Button to include data. I called it a DataButton and added a data member ( in this case an index number). That way when clicked it passes back its data. ( index number) Now I use the DataButton whenever I want it to hold information like an index or even a message.
It's because i in your anonymous function refers to the counter variable, not to the value:
from __future__ import print_function
x = [lambda: print(i) for i in range(10)]
for f in x:
f()
This produces an output of 10 consecutive 9s.
To get around this, you'd have to use two lambdas and shadow i with a second function (which creates your first function):
from __future__ import print_function
x = [(lambda i: (lambda: print(i)))(i) for i in range(10)]
for f in x:
f()
Although at that point, you'd be better off just making a named function:
def my_command(i):
def inner_function():
return my_function(i)
return inner_function
And using it like this:
tk.Button(root, text='button' + str(i), command=my_command(i))

Categories