Junior high school student K (second appearance) did not move as expected and started crying. I fixed it, but there was still a haze about nonlocal. I will leave it because the haze has disappeared.
Try to find out what is the cause.
Programs that don't work
import tkinter as tk
count = 0
def dispLabel():
count = count + 1
lbl.configure(text = str(count) + "Pressed twice")
root = tk.Tk()
root.geometry("300x80")
lbl = tk.Label(text="Count button")
btn = tk.Button(text="Press", command = dispLabel)
lbl.pack()
btn.pack()
tk.mainloop()
When the button is displayed and I press the button, I get an error.
Execution result
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\masa\Anaconda3\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "c:\Users\masa\OneDrive\document\python\lessen_tk.py", line 6, in dispLabel
count = count + 1
UnboundLocalError: local variable 'count' referenced before assignment
It's a basic mistake that you make a mistake if you don't understand scope and local variables.
I want to increment the global count in dispLabel (), but if there is a value assigned to count in dispLabel (), count will be recognized as a local variable and I will not be able to refer to the global variable ( If you don't assign to count, you can refer to global.) Therefore, if you refer to a value, you will get an error because it is before the value is assigned (see the bonus for details).
It's also Darui to explain, so I took a look at the example of the Python tutorial and had them understand the law.
Tutorial sample
def scope_test():
def do_local():
spam = "local spam"
def do_nonlocal():
nonlocal spam
spam = "nonlocal spam"
def do_global():
global spam
spam = "global spam"
spam = "test spam"
do_local()
print("After local assignment:", spam)
do_nonlocal()
print("After nonlocal assignment:", spam)
do_global()
print("After global assignment:", spam)
scope_test()
print("In global scope:", spam)
Mr. K who understood that the variables in the function are treated differently from the outside, I copied the tutorial and fixed it as follows.
amendment
def dispLabel():
nonlocal count
count = count + 1
lbl.configure(text = str(count) + "Pressed twice")
Execution result
Execution result
File "c:\Users\masa\OneDrive\document\python\lessen_tk.py", line 6
nonlocal count
^
SyntaxError: no binding for nonlocal 'count' found
Mr. T: "You can add nonlocal or global, but you can't." Me: What is this? ?? "If you set it to global count, it will work. I don't know." And make the tea muddy. (I'm sorry I can't explain) Of course, it worked when I made it global.
Why doesn't nonlocal allow you to refer to variables in the outer namespace? I knew nonlocal, but I didn't actually use it.
The nonlocal statement makes sure that the listed identifiers refer to the previously bound variable in the scope one outside except global. This is important because the default behavior of bindings first searches the local namespace. This statement allows the code inside to rebinding variables outside the local scope other than the global (module) scope.
Names listed in the nonlocal statement, unlike names listed in the global statement, must refer to a binding that already exists in the outer scope (the choice of scope in which the new binding should be created is ambiguous. Cannot be ruled out).
--In this example, the count outside the dispLabel () scope is global. Therefore, it is not a nonlocal target. --global will create a variable if executed, but nonlocal must exist before it can be created
If you just read the global variable count in a function without declaring global, you don't need to declare global. However, if there is an assignment to count, count will be recognized as a local variable. Note, it seems to be judged by the existence of the count = line, not by whether count = was executed. Even in the following case, count is recognized as a local variable and an exception of referenced before assignment is thrown on the line of a = (I didn't understand it, so I tried it and it was like this).
def dispLabel():
a = count + 1
if False:
count=a
lbl.configure(text = str(count) + "Pressed twice")
Recommended Posts