This is an idea I have be working on, trying to make a prototype. I think it is relevant to the topic of “Postponed annotations break inspection of dataclasses” discussed on python-dev. Perhaps it is too radical a change but I think it should be at least considered.
Currently the bytecode evaluation in CPython deals with frames and uses the f_globals and f_builtins properties to handle LOAD_GLOBAL, etc. I wonder, wouldn’t it make more sense if we gave frames a f_namespace property that would replace those two? In the normal case, f_namespace would be a module object. The module would take care of falling back to looking inside the builtins.
To me, this seems a cleaner design. Maybe we can find ways that the f_namespace object can more efficiently handle LOAD_GLOBAL and friends. E.g. the code object could have an optimized version that uses slot offsets and that code gets used if it matches the module (i.e. the module has matching slots). Since you can exec the code in a different namespace, we have to detect that and switch to the non-slot based lookups. That doesn’t seem too hard to do.
When dealing with importlib, import hooks, etc, the fact that we execute code in dicts rather than in modules also makes things more complicated, IMHO. There are times you want to know what is the module for this certain globals dict. I believe there is no clean solution for that now. You can crawl around in sys.modules to look it up by name. That’s ugly. If we just had the module in the first place, i.e. exec() takes the module as the globals, things would become neater.
Obviously we would have to work hard to maintain backwards compatibility. E.g. exec() would still have to accept a dict as the globals. I think internally, we would wrap the dict in an anonymous module. The C APIs that evaluate code would also still have to accept dicts. However, internally the normal and fast case could be to use f_namespace as a module or module-like object. As I said, I’m trying to prototype this idea. I don’t have all unit tests passing yet but I think there is hope it can work.