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

Nathaniel Smith njs at pobox.com
Tue Sep 5 18:52:31 EDT 2017

On Tue, Sep 5, 2017 at 3:03 PM, Larry Hastings <larry at hastings.org> wrote:
> I've written a PEP proposing a language change:
> https://www.python.org/dev/peps/pep-0549/
> The TL;DR summary: add support for property objects to modules.  I've
> already posted a prototype.

Interesting idea! It's definitely less arcane than the __class__
assignment support that was added in 3.5. I guess the question is
whether to add another language feature here, or to provide better
documentation/helpers for the existing feature.

If anyone's curious what the __class__ trick looks like in practice,
here's some simple deprecation machinery:

And here's what it looks like in use:

Advantages of PEP 549:
- easier to explain and use

Advantages of the __class__ trick:
- faster (no need to add an extra step to the normal attribute lookup
fast path); only those who need the feature pay for it

- exposes the full power of Python's class model. Notice that the
above code overrides __getattr__ but not __dir__, so the attributes
are accessible via direct lookup but not listed in dir(mod). This is
on purpose, for two reasons: (a) tab completion shouldn't be
suggesting deprecated attributes, (b) when I did expose them in
__dir__, I had trouble with test runners that iterated through
dir(mod) looking for tests, and ended up spewing tons of spurious
deprecation warnings. (This is especially bad when you have a policy
of running your tests with DeprecationWarnings converted to errors.) I
don't think there's any way to do this with PEP 549.

- already supported in CPython 3.5+ and PyPy3, and with a bit of care
can be faked on all older CPython releases (including, crucially,
CPython 2). PEP 549 OTOH AFAICT will only be usable for packages that
have 3.7 as their minimum supported version.

I don't imagine that I would actually use PEP 549 any time in the
foreseeable future, due to the inability to override __dir__ and the
minimum version requirement. If you only need to support CPython 3.5+
and PyPy3 5.9+, then you can effectively get PEP 549's functionality
at the cost of 3 lines of code and a block indent:

import sys, types
class _MyModuleType(types.ModuleType):
    def ...

    def ...
sys.modules[__name__].__class__ = _MyModuleType

It's definitely true though that they're not the most obvious lines of code :-)


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

More information about the Python-Dev mailing list