[MRAB] >> There's another question that hasn't been asked yet: what should locals() >> and globals() return?
[Tim, "globals()" is obvious, "locals()" can be surprising now] > ... And here recording the results of some code spelunking Dicts don't really have anything to do with how locals are implemented anymore; calling "locals()" now inside a function _constructs_ a dict on the fly out of lower-level implementation gimmicks, to be kinda-compatible with what locals() returned before nested scopes were introduced. The real distinctions of interest are recorded in the code object now, under these attributes, where I'm giving a fuller explanation than can be found in the docs, and where "referenced" doesn't distinguish between "binding merely retrieved" and "binding is changed": 1. co_varnames: tuple of names of locals not referenced in an enclosed local scope 2. co_cellvars: tuple of names of locals that are referenced in an enclosed local scope 3 .co_freevars: tuple of names local to an enclosing local scope and referenced in this enclosed code "locals()" now generally builds a dict out of all three of those name sources. #1 is the only one that made sense before nested scopes were introduced. The union of #1 and #2 is the set of names local to the code's scope; CPython implements their bindings in different ways, so needs to distinguish them. The names in #3 aren't local to the code block at all (they are local to some enclosing local scope), but for whatever reason are included in the code's "locals()" dict anyway. I would not have included them. For concreteness: def disp(func): print("for", func.__name__) code = func.__code__ for attr in "co_varnames", "co_cellvars", "co_freevars": print(" ", attr, getattr(code, attr)) def outer(): outer_only = 1 outer_used_inner = 2 outer_bound_by_inner = 3 def inner(): nonlocal outer_bound_by_inner inner_only = 4 outer_bound_by_inner = 5 inner_only = outer_used_inner inner() disp(outer) disp(inner) outer() And its output: for outer co_varnames ('outer_only', 'inner') co_cellvars ('outer_bound_by_inner', 'outer_used_inner') co_freevars () for inner co_varnames ('inner_only',) co_cellvars () co_freevars ('outer_bound_by_inner', 'outer_used_inner') _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/