[Python-Dev] PEP 549: Instance Properties (aka: module properties)

Guido van Rossum guido at python.org
Wed Sep 13 17:17:08 EDT 2017


On Wed, Sep 13, 2017 at 2:00 PM, Nathaniel Smith <njs at pobox.com> wrote:

> On Wed, Sep 13, 2017 at 11:49 AM, Guido van Rossum <guido at python.org>
> wrote:
> >  > Why not adding both? Properties do have their uses as does
> __getattr__.
> >
> > In that case I would just add __getattr__ to module.c, and add a recipe
> or
> > perhaps a utility module that implements a __getattr__ you can put into
> your
> > module if you want @property support. That way you can have both but you
> > only need a little bit of code in module.c to check for __getattr__ and
> call
> > it when you'd otherwise raise AttributeError.
>
> Unfortunately I don't think this works. If there's a @property object
> present in the module's instance dict, then __getattribute__ will
> return it directly instead of calling __getattr__.
>

Hm, that's a good point. One would have to introduce some kind of
convention where you can write properties with a leading _:

@property
def _foo(): return 42

and then a utility __getattr__ like this:

def __getattr__(name):
    g = globals()
    name = '_' + name
    if name in g:
        return g[name]()
    raise AttributeError(...)


> (I guess for full property emulation you'd also need to override
> __setattr__ and __dir__, but I don't know how important that is.)
>

At that point maybe __class__ assignment is better.


> We could consider letting modules overload __getattribute__ instead of
> __getattr__, but I don't think this is viable either -- a key feature
> of __getattr__ is that it doesn't add overhead to normal lookups. If
> you implement deprecation warnings by overloading __getattribute__,
> then it makes all your users slower, even the ones who never touch the
> deprecated attributes. __getattr__ is much better than
> __getattribute__ for this purpose.
>

Agreed.

Alternatively we can have a recipe that implements @property support
> using __class__ assignment and overriding
> __getattribute__/__setattr__/__dir__, so instead of 'from
> module_helper.property_emulation import __getattr__' it'd be 'from
> module_helper import enable_property_emulation;
> enable_property_emulation(__name__)'. Still has the slowdown problem
> but it would work.
>

The emulation could do something less drastic than __class__ assignment --
it could look for globals that are properties, move them into some other
dict (e.g. __properties__), and install a __getattr__ that looks things up
in that dict and calls them.

def __getattr__(name):
    if name in __properties__:
        return __properties__[name]()
    raise AttributeError(...)

Still, proposals for sys.py notwithstanding, I'm worried that all of this
is a solution looking for a problem. Yes, it's a cute hack. But is it art?

-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20170913/648f57bb/attachment.html>


More information about the Python-Dev mailing list