https://mail.python.org/pipermail/python-dev/2017-November/150528.html
Python’s descriptor protocol requires that descriptorsbe members of thetype of an object. This PEP proposesan extension to the descriptor protocol allowing use ofthe descriptor protocol for members ofinstances. Thiswould permit using properties in modules.
Python’s descriptor protocol guides programmers towardselegant API design. If your class supports a data-likemember, and youmight someday need to run code whenchanging the member’s value, you’re encouraged tosimply declare it as a simple data member of the classfor now. If in the future you do need to run code, youcan change it to a “property”, and happily the API doesn’tchange.
But consider this second bit of best-practice Python API design:if you’re writing a singleton, don’t write a class, just buildyour code directly into a module. Don’t make your usersinstantiate a singleton class, don’t make your users have todereference through a singleton object stored in a module,just have module-level functions and module-level data.
Unfortunately these two best practices are in opposition.The problem is that properties aren’t supported on modules.Modules are instances of a single genericmodule type,and it’s not feasible to modify or subclass this type to adda property to one’s module. This means that programmersfacing this API design decision, where the data-like memberis a singleton stored in a module, must preemptively addugly “getters” and “setters” for the data.
Adding support for module properties in pure Python has recentlybecomepossible;as of Python 3.5, Python permits assigning to the__class__attribute of module objects, specifically for this purpose. Here’san example of using this functionality to add a property to a module:
importsys,typesclass_MyModuleType(types.ModuleType):@propertydefprop(self,instance,owner):...sys.modules[__name__].__class__=_MyModuleType
This works, and is supported behavior, but it’s clumsy and obscure.
This PEP proposes a per-type opt-in extension to the descriptorprotocol specifically designed to enable properties in modules.The mechanism is a way to honor the descriptor protocol formembers ofinstances of a class without the member being declaredas a class variable.
Although this is being proposed as a general mechanism, the authorcurrently only foresees this as being useful for module objects.
The basic idea is simple: modify thetp_descr_get andtp_descr_setfunctions exposed byPyModule_Type to inspect the attribute interactedwith, and if it supports the descriptor protocol, call the relevantexposed function.
Our implementation faces two challenges:
Both challenges can be solved with the same approach: we define a new“fast subclass” flag that means “This object is a descriptor, and itshould be honored directly when this object is looked up as anattribute of an instance”. So far this flag is only set on twotypes:property andcollections.abc.InstanceDescriptor.The latter is an abstract base class, whose only purpose isto allow user classes to inherit this “fast subclass” flag.
A prototype of this functionality is under developmentat GitHub[github].
Armin Rigo essentially proposed this mechanism when presentedwith the idea of “module properties”, and educated the authorboth on the complexities of the problem and the proper solution.Nathaniel J. Smith pointed out the 3.5 extension about assigningto__class__ on module objects, and provided the example.
This document has been placed in the public domain.
Source:https://github.com/python/peps/blob/main/peps/pep-0549.rst
Last modified:2025-02-01 08:59:27 GMT