On Sun, 2 Oct 2016 04:06 pm, Chris Angelico wrote: > On Sun, Oct 2, 2016 at 3:19 PM, Steve D'Aprano > <steve+pyt...@pearwood.info> wrote: >> In IronPython, you could have the following occur in a function locals, >> just as it could happen CPython for globals: >> >> - delete the name binding "x" >> - which triggers a dictionary resize >> - bind a value to x again >> - because the dictionary is resized, the new "slot" for x is in a >> completely different position of the dictionary to the old one >> >> There is no user-visible difference between these two situations. Your >> code works the same way whether it is executed inside a function or at >> the global top level, whether functions use the CPython local variable >> optimization or not. > > Hmm, interesting. I don't have IronPython here, but maybe you can tell > me what this does: > > print(str) > str = "demo" > print(str) > del str > print(str) > > and the same inside a function. In CPython, the presence of 'str = > "demo"' makes str function-local, ergo UnboundLocalError on the first > reference; but globals quietly shadow built-ins, so this will print > the class, demo, and the class again. If IronPython locals behave the > way CPython globals behave, that would most definitely be a > user-visible change to shadowing semantics.
That's a nice catch! But its not a difference between "update binding" versus "new binding" -- its a difference between LOAD_FAST and LOAD_whatever is used for things besides locals. steve@orac:~$ ipy IronPython 2.6 Beta 2 DEBUG (2.6.0.20) on .NET 2.0.50727.1433 Type "help", "copyright", "credits" or "license" for more information. >>> def func(): ... print(str) ... str = 1 ... >>> func() Traceback (most recent call last): UnboundLocalError: Local variable 'str' referenced before assignment. Although IronPython does the same thing as CPython here, I'm not 100% sure that this behaviour would be considered language specification or a mere guideline. If the author of an alternate implementation wanted to specify a single name resolution procedure: - look for local variable; - look for nonlocal; - look for global; - look for builtin; - fail rather than two: (1) - look for local; - fail; (2) - look for nonlocal; - look for global; - look for builtin; - fail I'm not entirely sure that Guido would say No. I think that "fail early if the local doesn't exist" as CPython does would be permitted rather than mandatory. But I could be wrong. By the way, here's an example showing that IronPython does allowing writing to locals to affect the local namespace: >>> def func(): ... locals()['x'] = 1 ... print(x) ... if False: ... x = 9999 ... >>> func() 1 And *that* behaviour is most definitely allowed -- the fact that writing to locals() isn't supported by CPython is most definitely an implementation- specific limitation, not a feature. -- Steve “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse. -- https://mail.python.org/mailman/listinfo/python-list