Discussion:
[Tkinter-discuss] Button command callback question -- Part 2
GKalman
2011-07-18 12:24:53 UTC
Permalink
Thanks for the replies for my earlier question. I should have stated my
question in a better way.
My question is related to SCOPE!
For example:
#====================================
from Tkinter import *
#-------------------------------------------------
def doIt():
print x
#------------------------------------------------
root=Tk()

btn=Button(root,text="DO",bg="cyan",command=doIt)
btn.pack(side=BOTTOM)

x=11


#NOTE that it works even when the mainloop() method below is commented
out!!!!
#root.mainloop()
#===================================================================

so: if
(1) there is no mainloop()
(2) x=11 is declared in the MAIN part
(3) command=doIt() has no argument
(4) doIt() fn appears ahead of the x=11 statement

My Question is: why x=11 is within the scope of the doIt() callback fn?
--
View this message in context: http://old.nabble.com/Button-command-callback-question----Part-2-tp32082790p32082790.html
Sent from the Python - tkinter-discuss mailing list archive at Nabble.com.
Michael Lange
2011-07-18 18:21:07 UTC
Permalink
Hi,

Thus spoketh GKalman <kalman_g at msn.com>
unto us on Mon, 18 Jul 2011 05:24:53 -0700 (PDT):

(...)
Post by GKalman
#NOTE that it works even when the mainloop() method below is commented
out!!!!
#root.mainloop()
#===================================================================
so: if
(1) there is no mainloop()
(2) x=11 is declared in the MAIN part
(3) command=doIt() has no argument
(4) doIt() fn appears ahead of the x=11 statement
My Question is: why x=11 is within the scope of the doIt() callback fn?
Here when root.mainloop() is commented out, the call to
$ python test.py
immediately returns ;) Of course you don't need to explicitely call
mainloop() when you run python in interactive mode from a terminal.

Besides this I cannot see anything surprising in the behavior of the
code example. When you define x=11 you add an object "x" to the global
namespace. When doIt() is called and the print x command is being
executed, the interpreter will first look if an object x is defined
within the function's namespace and then look within the global namespace
for such an object. Only when it cannot find such an object in any
available namespace an error will be raised.
Of course the contents of the function body are not evaluated before the
function is actually called. So it is not important if doIt is defined
before x , but only if x is already defined when doIt() is called.

Maybe it helps you understand what happens if you change your example a
little. If you change the doit() definition like

def doIt():
x = 2
print x

it will print 2 instead of 11 . It is important to understand that the
"outer" x will not be changed by calls to this function as you can verify
by e.g. adding a second button that will call the original version of
your doIt() function, or by changing it a little more:

def doIt():
print x
def foo():
x=2
print x
foo()

Now it will print first 11, then 2 , but without overriding the "outer" x,
as you can see by repeatedly pressing the button.

If you want to change the "outer" (=global) x , you need to add the
"global" statement:

def doIt():
print x
def foo():
global x
x+=1
print x
foo()

I hope this helps

Michael


.-.. .. ...- . .-.. --- -. --. .- -. -.. .--. .-. --- ... .--. . .-.

Death. Destruction. Disease. Horror. That's what war is all about.
That's what makes it a thing to be avoided.
-- Kirk, "A Taste of Armageddon", stardate 3193.0
Lion Kimbro
2011-07-18 18:59:00 UTC
Permalink
I would also add a caution:

If you assign x *anywhere* within the function, a prior use will fail...

def foo():
print x # raises UnboundLocalError,
x = 10 # ...because the interpreter knows that x is local.

Only unassigned values are searched for in the global namespace, if not
locally declared.

I think the reason it's like this, is to keep variables in one function in
one scope,
for sanity's sake.
Post by Michael Lange
Hi,
Thus spoketh GKalman <kalman_g at msn.com>
(...)
Post by GKalman
#NOTE that it works even when the mainloop() method below is commented
out!!!!
#root.mainloop()
#===================================================================
so: if
(1) there is no mainloop()
(2) x=11 is declared in the MAIN part
(3) command=doIt() has no argument
(4) doIt() fn appears ahead of the x=11 statement
My Question is: why x=11 is within the scope of the doIt() callback fn?
Here when root.mainloop() is commented out, the call to
$ python test.py
immediately returns ;) Of course you don't need to explicitely call
mainloop() when you run python in interactive mode from a terminal.
Besides this I cannot see anything surprising in the behavior of the
code example. When you define x=11 you add an object "x" to the global
namespace. When doIt() is called and the print x command is being
executed, the interpreter will first look if an object x is defined
within the function's namespace and then look within the global namespace
for such an object. Only when it cannot find such an object in any
available namespace an error will be raised.
Of course the contents of the function body are not evaluated before the
function is actually called. So it is not important if doIt is defined
before x , but only if x is already defined when doIt() is called.
Maybe it helps you understand what happens if you change your example a
little. If you change the doit() definition like
x = 2
print x
it will print 2 instead of 11 . It is important to understand that the
"outer" x will not be changed by calls to this function as you can verify
by e.g. adding a second button that will call the original version of
print x
x=2
print x
foo()
Now it will print first 11, then 2 , but without overriding the "outer" x,
as you can see by repeatedly pressing the button.
If you want to change the "outer" (=global) x , you need to add the
print x
global x
x+=1
print x
foo()
I hope this helps
Michael
.-.. .. ...- . .-.. --- -. --. .- -. -.. .--. .-. --- ... .--. . .-.
Death. Destruction. Disease. Horror. That's what war is all about.
That's what makes it a thing to be avoided.
-- Kirk, "A Taste of Armageddon", stardate 3193.0
_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss at python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tkinter-discuss/attachments/20110718/ab887fdd/attachment.html>
Loading...