On 9/11/2017 10:03 AM, João Matos wrote:
Hello,
I would like to suggest that nonlocal should be given the same creating
power as global.
If I do global a_var it creates the global a_var if it doesn't exist.
The global declaration does not create anything, but it redirects
subsequent binding.
I think it would be great that nonlocal maintained that power.
This way when I do nonlocal a_var
it would create a_var in the imediate parent environment, if it didn't
exist.
'Creating new variables' was discussed and rejected when nonlocal was
added. That may partly be for technical reasons of not nonlocal is
implemented. But there are also problems of ambiguity. Consider this
currently legal code.
def f(a):
def g(): pass
def h():
nonlocal a
a = 1
You proposal would break all such usages that depend on skipping the
immediate parent environment. 'nonlocal a' effectively means 'find the
closest function scope with local name a' and I strongly doubt we will
change that. If you want 'nonlocal a' to bind in g, explicitly add a to
g's locals, such as with 'a = None'.
Without nonlocal creation powers I have to create global variables or
local variables after master=Tk() (in the following example):
There is nothing wrong with either.
from tkinter import StringVar, Tk
from tkinter.ttk import Label
def start_gui():
def change_label():
_label_sv.set('Bye Bye')
def create_vars():
global _label_sv
_label_sv = StringVar(value='Hello World')
def create_layout():
Label(master, textvariable=_label_sv).grid()
def create_bindings():
master.bind('<Escape>', lambda _: master.destroy())
master.bind('<Return>', lambda _: change_label())
master = Tk()
create_vars()
create_layout()
create_bindings()
master.mainloop()
if __name__ == '__main__':
start_gui()
In the version above, you could simplify by removing start_gui and put
the operative code from 'master = Tk()' on down in the main clause.
This is standard practice for non-OOP tkinter code.
With nonlocal creation powers it would become a start_gui local variable
(no global) but I could have a function to create the vars instead of
having to add them after master=Tk():
from tkinter import StringVar, Tk
from tkinter.ttk import Label
def start_gui():
def change_label():
label_sv.set('Bye Bye')
def create_vars():
nonlocal label_sv
label_sv = StringVar(value='Hello World')
def create_layout():
Label(master, textvariable=label_sv).grid()
def create_bindings():
master.bind('<Escape>', lambda _: master.destroy())
master.bind('<Return>', lambda _: change_label())
master = Tk()
create_vars()
create_layout()
create_bindings()
master.mainloop()
if __name__ == '__main__':
start_gui()
Initializing the outer function local, here adding 'label_sv = None', is
the price of wanting to create a class with functions instead of a class
definition.
I know that I could also do it with OOP, but this way is more concise
(OOP would add more lines and increase the lines length, which I
personally dislike)
This example is very simple, but if you imagine a GUI with several
widgets, then the separation between vars, layout and bindings becomes
useful for code organization.
This is what classes are for. Either use 'class' or explicitly name the
local of the outer function acting as a class.
--
Terry Jan Reedy
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/