[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