On Mon, Jun 22, 2015 at 3:03 AM, Nick Coghlan <[email protected]> wrote:
> On 22 June 2015 at 08:46, Ivan Levkivskyi <[email protected]> wrote:> >> >> > On 21 June 2015 at 22:05, Guido van Rossum <[email protected]> wrote:> >>> >> On Sun, Jun 21, 2015 at 6:22 PM, Ivan Levkivskyi <[email protected]>> >> wrote:> >>>> >>> It is still not clear whether Guido's comment still stands for not> >>> raising an UnboundLocalError in class definitions but using globals> instead.> >>> >>> >> Can you phrase this in the form of an example, showing what it currently> >> does and what you think it should do, instead?> >>> >> > Here is an example:> >> > x = "xtop"> > y = "ytop"> > def func():> > x = "xlocal"> > y = "ylocal"> > class C:> > print(x)> > print(y)> > y = 1> > func()> >> > prints> >> > xlocal> > ytop> >> > Intuitively, one might think that it should raise UnboundLocalError or> print> > ylocal instead of ytop.> > This question was discussed 13 years ago and then you said that this> lookup> > in globals> > is an intentional behavior.> >> > This behavior is not documented, and I started an issue on bug tracker> > about documenting it.> > Then, Eric proposed to ask you again, whether this is still an> intentional> > behavior.>> Diving into some bytecode details:>In particular, the bytecode for C is:>>> dis.dis(func.__code__.co_consts[3]) 6 0 LOAD_NAME 0 (__name__) 3 STORE_NAME 1 (__module__) 6 LOAD_CONST 0 ('func.<locals>.C') 9 STORE_NAME 2 (__qualname__) 7 12 LOAD_NAME 3 (print) 15 LOAD_CLASSDEREF 0 (x) 18 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 21 POP_TOP 8 22 LOAD_NAME 3 (print) 25 LOAD_NAME 4 (y) 28 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 31 POP_TOP 9 32 LOAD_CONST 1 (1) 35 STORE_NAME 4 (y) 38 LOAD_CONST 2 (None) 41 RETURN_VALUE>>>> We added LOAD_CLASSDEREF> (https://docs.python.org/3/library/dis.html#opcode-LOAD_CLASSDEREF) a> while back to account for the fact that __prepare__ may inject locals> into a class body that the compiler doesn't know about. Unlike> LOAD_DEREF, LOAD_CLASSDEREF checks the locals before it checks the> closure cell.>> However, neither LOAD_CLASSDEREF *nor* LOAD_DEREF is used for names> that are *assigned* in the class body - those get flagged as local> variables, so we end up emitting LOAD_NAME for them, and hence ignore> any nonlocal variables with that name. If a module global or builtin> exists, we'll find that, otherwise we'll throw NameError.>> With nested_scopes having been the default since 2.2, and accounting> for the fact that folks *do* write code like "name = name" at class> scope and expect it to "do the right thing", it seems reasonable to me> to just make this work properly, rather than having to explain why it> doesn't work as one might expected based on the behaviour of module> level class definitions and other references to nonlocal variables> from a class body.>But what *is* the correct behavior? I suspect people's intuitions differ.If you think of this as similar to function scopes you're likely to bewrong.Also, since classes inside functions are commonly used in unit tests (atleast mine :-), I worry that *any* changes in this behavior might breakworking code (no matter how much that "working" could be considered anaccident, it's still going to be a bear to debug if this happens to you).-- --Guido van Rossum (python.org/~guido)_______________________________________________Python-Dev mailing list[email protected]https://mail.python.org/mailman/listinfo/python-devUnsubscribe:https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com