[Tkinter-discuss] Button command callback question -- Part 2

Michael Lange klappnase at web.de
Mon Jul 18 20:21:07 CEST 2011


Hi,

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

(...)  
> 
> #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


More information about the Tkinter-discuss mailing list