On 2/26/19, Gregory Ewing <greg.ew...@canterbury.ac.nz> wrote: > Thomas Jollans wrote: >> I imagine there's a justification for the difference in behaviour to do >> with the fact that the body of a class is only ever executed once, while >> the body of a function is executed multiple times. > > I suspect there isn't any deep reason for it, rather it's just > something that fell out of the implementation, in particular > the decision to optimise local variable access in functions > but not other scopes.
At the module level, this goes unnoticed since globals and locals are the same dict, but we can observe it in an exec() call if we use separate globals and locals . For example: >>> x = 0 >>> locals = {} >>> exec('x = x + 1', globals(), locals) >>> x 0 >>> locals {'x': 1} In terms of implementation, the LOAD_NAME instruction that's used in unoptimized code looks in the locals, globals, and builtins scopes, in that order. The intent is to allow locals to shadow globals and builtins, and globals to shadow builtins. It also allows for temporary shadowing. Optimized code supports the former (via LOAD_GLOBAL), but not the latter. For example: unoptimized: >>> exec(r''' ... len = lambda x: 42 ... print(len('spam')) ... del len ... print(len('spam')) ... ''') 42 4 optimized: >>> def f(): ... len = lambda x: 42 ... print(len('spam')) ... del len ... print(len('spam')) ... >>> f() 42 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in f UnboundLocalError: local variable 'len' referenced before assignment -- https://mail.python.org/mailman/listinfo/python-list