[Python-ideas] Idea to support lazy loaded names.
Nick Coghlan
ncoghlan at gmail.com
Tue Oct 7 13:26:14 CEST 2014
On 7 October 2014 13:51, Terry Reedy <tjreedy at udel.edu> wrote:
> On 10/6/2014 11:30 PM, Steven D'Aprano wrote:
>
>> This is relevant because modules are instances, and module attributes
>> live in the instance __dict__.
>
> So a 'solution' might be to make modules be instances (but with no __new__
> or __init__) of a module metaclass, so that module dicts could act like
> class dicts with respect to descriptors. I have no idea how much code this
> would break ;-).
As Steven noted, making such a change by default would actually break
the world, since every module level function would break when it
started being treated as a method instead:
>>> def f(): pass
...
>>> hasattr(f, "__get__")
True
Anything related to changing module attribute lookup also needs to
deal with the fact that manipulating the module namespace via
globals() and the "global" directive is a fully supported feature.
This is why models which put something that *isn't* a normal module
(such as an ordinary class object) in sys.modules tend to be
preferred. That approach is already fully supported, since the import
system *retrieves the result from sys.modules*, rather than trusting
what the import hooks return - that gives the module the ability to
replace itself in sys.modules as a side effect of the import process.
For example, here's a rough (untested) sketch of one possible way to
do a lazily calculated module attribute today:
# rest of the module
...
class _ThisModule:
@property
def calculated_attribute(self):
return 42
_ThisModule.__dict__.update(globals())
for k, v in _ThisModule.__dict__.items():
if callable(v):
setattr(_ThisModule, k, staticmethod(v))
import sys
sys.modules[__name__] = _ThisModule()
You could potentially wrap most of that dance up in a "replace_module"
helper function and stick it somewhere in importlib.
Cheers,
Nick.
P.S. This is a variant of approach #5 from Andrew's list. Approach #3
would allow code along the lines of "__class__ = _ThisModule",
potentially simplifying the situation even further than a helper
function could.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-ideas
mailing list