[Python-ideas] "Loose" descriptors

Nathaniel Smith njs at pobox.com
Mon Mar 30 01:23:17 CEST 2015


On Sat, Mar 28, 2015 at 10:36 PM, Andrew Barnert
<abarnert at yahoo.com.dmarc.invalid> wrote:
> On Mar 28, 2015, at 19:17, Steven D'Aprano <steve at pearwood.info> wrote:
>>
>>> On Sun, Mar 29, 2015 at 11:51:31AM +1300, Greg Ewing wrote:
>>> James Edwards wrote:
>>>> I envision (but with no real knowledge of the implications of this)
>>>> that just as python identifies that `val` in `Holder.__dict__`
>>>> implements `__get__`, python could similarly identify that `val` in
>>>> `globals()` (or `sys.modules[__name__].__dict__`, or wherever is more
>>>> appropriate) implements `__get__` and handle the indirection.
>>>
>>> This would slow down *all* lookups of global names in
>>> order to support a rarely-used feature. Since global
>>> name lookup is critical performance-wise, this is
>>> likely to meet a lot of resistance.
>>>
>>> Similar arguments have been made concerning the
>>> support of descriptors in module namespaces, which
>>> is a closely related idea.
>>
>> I don't think it's a closely related idea, I think it is *exactly* the
>> same idea. If I've understood him correctly, James wants to use
>> descriptors in global variables, i.e. module namespaces, not just class
>> attributes.
>
> Yeah, that's how I interpreted it too.
>
> The obvious way to do this is to provide some way for a module to define not only an instance of the module type, but a subclass and an instance of that subclass. The subclass then provides a natural place for the descriptors to live (and a natural answer to what gets passed for inst and typ).
>
> There was a proposal for something very much like that some time late last year, IIRC, which might be worth digging up.

It got implemented. In 3.5, you can do:

# mymodule.py:
class MyModuleType(types.ModuleType):
    @property
    def someattr(self):
        print("Fetching someattr!")
        return 1

sys.modules[__name__].__class__ = MyModuleType

and now accessing mymodule.someattr will print a message.

This is fast -- it doesn't add any overhead for regular module
attribute lookups. OTOH it only works for module attribute lookups,
not for direct accesses to the global dict. So code executing inside
the module namespace can't write a bare "someattr" to refer to the
property; only external users of the module see "someattr".

There's some code to make this available on all versions of CPython here:
  https://github.com/njsmith/metamodule/
which I'll clean up slightly and put up on pypi Any Day Now...

-n

-- 
Nathaniel J. Smith -- http://vorpus.org


More information about the Python-ideas mailing list