[Python-ideas] Give nonlocal the same creating power as global

João Matos jcrmatos at gmail.com
Mon Sep 11 13:32:18 EDT 2017


Hello,

You're correct. The idea is to give nonlocal the same ability, redirect 
subsequent bindings if the variable doesn't exist.

No, what I said is that it would only create the var if it didn't exist.
That means that the current behaviour of nonlocal to check all previous 
envs (except global) would be the same.
The variable would only be created if it ididn't exist in all parent envs.

The downside of the global example is that it is "poluting" the globals.

The reason it is inside a function is that it is called from another 
module. The main module does some checks and only if the checks are ok 
it calls the gui module.

Best regards,

João Matos


On 11-09-2017 16:51, Terry Reedy wrote:
> 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.
>



More information about the Python-ideas mailing list