Closed BCSharp closed 2 years ago
The nonlocal
case is indeed odd, not what I would expect. Seems obscure enough that it's unlikely anyone would be relying on this behaviour. So, as long as it's not causing any CPython test failures, I'm fine with fixing it. We could have a test case pointing to the details (which could fail if CPython ever changes to match).
A dictionary lookup behaviour is standard for classes. This means that any locally referenced name is first looked up in the class attribute dictionary (local namespace), before looked up in the enclosing lexical scopes. This is true even if the variable to be looked up is late-bound, e.g. introduced at runtime by modifying
locals()
or though metaclass__prepare__
. This behaviour is already implemented in #1151 in general and in recent #1551 for metaclasses.For instance:
However, when a variable is explicitly declared global, the default namebinding rules are overridden and the name has to resolve to a global variable:
This is not how IronPython handles it currently.
An interesting story emerges when the variable is declared
nonlocal
rather thanglobal
. One (like me) would expect it too to override default namebinding rules and force lexical lookup. However, all CPython versions up to and including 3.10 still do local dictionary lookup:IronPython currently matches it, simply because none of this explicit declaration is taken into account yet. But as a programmer and IronPython developer I see it as a bug. Perhaps nobody reported it yet to CPython, or a report has been made, but got a very low priority. After all, this is a very unlikely piece of code that would reveal the bug. And arguably bad style.
Another demonstration that this is likely a bug rather a deliberate design is that references are resolved differently depending whether they are read (namespace lookup) or written (lexical lookup). To modify the example above a little:
I'd prefer to implement the behaviour that seems correct, though feel uncomfortable deviating from CPython. But if I won't do it now, and then CPython one day changes its behaviour, who will remember the fix that now seems easy.