Problem with a dialog

Steven D'Aprano steve+comp.lang.python at pearwood.info
Thu Dec 11 07:03:43 EST 2014


ast wrote:

> Hello
> 
> I provide two almost identical small test case programs.
> The first one works as expected, 'True' is printed on the
> console.
> With the second one Python complains that 'test' is not
> known. I dont understand why.


> #####################
> ## Second
> #####################
>  
> from tkinter import *
> import tkinter.simpledialog
> 
> class MyDialog(tkinter.simpledialog.Dialog):
> 
>     def body(self, master):
>         print(test)

Here, "test" must be a global variable. Since the body() method doesn't
assign to the name "test" (e.g. a line like "test = 23") that makes it a
global.


>     def apply(self):
>         pass
> 
> def try_():
>     test = True
>     setup = MyDialog(root)

Here, the try_() function creates two local variables, "test" and "setup".
The important thing here is that "test" is local to the function, not
global.

That means that when MyDialog's body() method runs, it looks for a global
variable "test", but there isn't one. The local variable inside try_() is
invisible to it.

You can make "test" global by declaring it global:

def try_():
    global test
    test = True
    setup = MyDialog(root)



If that solves your problem to your satisfaction, you can stop reading now.



Still here? Good :-)

To be a little more advanced for a moment... what you tried to do (possibly
inadvertently?) is possible in some computer languages, but not Python. In
most languages, the rule is that functions (and methods) can see the
following variables:

- variables inside the function itself (local variables)

- variables inside nested functions [see below], sometimes 
  called "nonlocal variables"

- global variables defined at the top level of the module or 
  program (outside of any function)


but not variables inside functions that *call* your function. This is
called "static scoping" or "lexical scoping".

What's a nested function? That's just when you put a function inside another
function:

def outer():
    x = 23
    def inner():
        return 3*x
    return inner() + 1


In this case, inner() is nested inside outer(), so it can see outer()'s
local variables, such as "x". Nothing else can see inner(), since it is
local to outer().

As I said, most programming languages work like this. But a small minority
use a different system, called "dynamic scoping". In dynamic scoping, it
doesn't matter *where* a function is defined, only where it is called. With
dynamic scoping, your code would have worked correctly.

If you are used to languages like Javascript, you may have done that
deliberately, thinking Python worked the same way. It doesn't.


-- 
Steven




More information about the Python-list mailing list