== Some trivia about Python frame objects Since I've been [[poking MisleadingFLocals]] [[around SpelunkingFBuiltins]] in this area of CPython lately, here's some trivia associated with frame objects. First, one might wonder if code executing at the module level literally has a CPython frame struct with ((f_locals)) being the same as ((f_globals)), or if the C code just leaves ((f_locals)) null and fixes things up behind the scenes when you look from Python code. The answer turns out to be that CPython frame structures always have a real ((f_locals)) (Python) dictionary, and in module level code it is just another reference to the globals as you'd expect. This surprised me because I had always assumed that ((f_locals)) dictionaries for function-level frames were only materialized on (rare) demand. Instead there's always a dictionary, although its contents are allowed to get out of date with the [[real local variables WhyLocalVarsAreFast]] as long as no Python code is looking at it. (There are various interesting efficiency hacks to make creation and destruction of frame objects faster than you might expect.) Second and probably obviously: there's no way to directly update the builtins namespace. This is both a language issue (there's no _builtin_ analog to the _global_ keyword) and an issue with the [[bytecode interpreter WhyLocalVarsAreFast]]; in order to support direct updates of the builtin namespace, the bytecode interpreter would need a new ((STORE_BUILTIN)) opcode, as ((STORE_GLOBAL)) naturally only updates the ((f_globals)) namespace. Now, consider the following code: > eval = eval > def t(): > global file > file = file This peculiar do-nothing code actually does do something: it creates module-level shadows of the _eval_ and _file_ builtins. This is one of the least obvious cases in which the left hand side of an assignment can be in a different namespace than the right hand side despite using the exact same variable names. (Or not, if you've already executed these statements once.) (Previously I said that there were [[only two cases DefAsStatementConsequence]] of such namespace differences; I was wrong then, or at least insufficiently perverse.)