[Tutor] Question about why a list variable is apparently global.

Alan Gauld alan.gauld at btinternet.com
Thu Nov 27 01:11:16 CET 2014


On 26/11/14 23:23, boB Stepp wrote:

> def printLabel():
>      print "Button number ", var.get(), " was pressed."
>      print "You selected this option:", l[var.get() - 1][0]
>
...
> buttonNumber = []
> l = [("Brain_Partial", 1), ("Brain_Whole", 2),
>                          ("Head & Neck", 3), ("Chest", 4), ("Breast_Whole", 5),
>                          ("Breast_Partial", 6), ("Abdomen", 7), ("Pelvis", 8),
>                          ("Prostate", 9)]
> var = IntVar()
> for text, value in l:
>      buttonNumber.append(Radiobutton(root, text = text, value = value,
>                      command=printLabel, variable = var).pack(anchor=W))

> First question: How can the printLabel() function see the list
> variable, l, defined outside of this function? I thought that
> functions only had access to variables local to the function and
> whatever else is passed to it during the function call.

...and read access to global variables; of which l is one.
You can also get write access by declaring the variable as global inside 
the function. That will work here because you made l global.

Better is to use a parameter of printLabel() and then pass 'l'
in when you call it when the button is pressed. That way the data can be 
anywhere or you can even use more than one data source for the same 
function. How do you do that? Declare another function:

def printLabel(data):
     # use data here

def callPrintLabel():
     return printLabel(l)

Then pass the new function name into your command.

buttonNumber.append(Radiobutton(root, text = text,
                     value = value, command=callPrintLabel,
                     variable = var).pack(anchor=W))


But since callPrintLabel()'s a one liner we can bypass the
definition and use a lambda with a default parameter instead:

buttonNumber.append(Radiobutton(root, text = text,
                     value = value, command=lambda d=l: printLabel(d),
                     variable = var).pack(anchor=W))

Now when the button is clicked it will call the lambda which uses
l as the default value for its parameter d. And it then calls
printLabel(d).

> Second: Will the statements near the end that return the display
> screen's width and height be a reliable way of determining the user's
> actual monitor settings? My intent is to use this information to
> appropriately scale and position windows; not only in this particular
> simple window, but in others to come which will potentially be large
> and complex. I have tested this on two different sized monitors where
> I work and so far it has given the correct results.

It should do.

> Third: I am always open to stylistic comments and how to be more pythonic!

Any sizeable GUI tends to be easier using OOP techniques. Most Tkinter 
GUI tutorials show how to write OOP based Tkinter code. Otherwise you 
wind up with an awful lot of global variables to remember and control.

> Fourth: And perhaps this should go into a new thread, I am not sure I
> understand the full intent and use of Tkinter's Variable class. Any
> clarification on this would be welcome as well.

It's just a convenience feature provided by Tk and carried through to 
Tkinter. I rarely use it myself, finding it nearly as easy to do the 
management myself. But it does save a few lines...

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos




More information about the Tutor mailing list