Martin Panter added the comment: Calling exec() with only one argument is equivalent to exec(..., globals(), locals()). It does not create a new scope for names. So an equivalent of your three-level example is more like
>>> i = 'global' >>> def f(): ... i = 'nonlocal' ... class_locals = dict() ... exec("print(i)\ni = 'local'\nprint(i)\n", globals(), class_locals) ... >>> f() global local If exec() worked like a function rather than a class, the first print(i) would trigger an UnboundLocalError instead: >>> i = 'global' >>> def f(): ... i = 'nonlocal' ... def g(): ... print(i) ... i = 'local' ... g() ... >>> f() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 6, in f File "<stdin>", line 4, in g UnboundLocalError: local variable 'i' referenced before assignment In your first exec() example, i='nonlocal' is passed to exec() via the default locals parameter, and the exec() uses that value rather than deferring to its globals. To be a free variable, “i” has to be used but not defined. Even if you dropped the “i = 'local' ” assignment, it is still defined via the implicit locals parameter. Your proposal for “Interaction with dynamic features” sounds reasonable. ---------- nosy: +martin.panter _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue26225> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com