Added PEP 549, "Instance Properties".
This commit is contained in:
parent
0e65aeaa60
commit
fa830f9d46
|
@ -0,0 +1,118 @@
|
|||
PEP: XXXX
|
||||
Title: Instance Properties
|
||||
Version: $Revision$
|
||||
Last-Modified: $Date$
|
||||
Author: larry@hastings.org (Larry Hastings)
|
||||
Status: Draft
|
||||
Type: Standards Track
|
||||
Created: 4-Sep-2017
|
||||
Python-Version: 3.7
|
||||
Post-History: 4-Sep-2017
|
||||
|
||||
|
||||
Abstract
|
||||
--------
|
||||
|
||||
Python's descriptor protocol requires that descriptors
|
||||
be members of the *type* of an object. This PEP proposes
|
||||
an extension to the descriptor protocol allowing use of
|
||||
the descriptor protocol for members of *instances.* This
|
||||
would permit using properties in modules.
|
||||
|
||||
Rationale
|
||||
---------
|
||||
|
||||
Python's descriptor protocol guides programmers towards
|
||||
elegant API design. If your class supports a data-like
|
||||
member, and you *might* someday need to run code when
|
||||
changing the member's value, you're encouraged to
|
||||
simply declare it as a simple data member of the class
|
||||
for now. If in the future you do need to run code, you
|
||||
can change it to a "property", and happily the API doesn't
|
||||
change.
|
||||
|
||||
Unfortunately this doesn't work with modules. Modules are
|
||||
instances of a single generic ``module`` type, and it's not
|
||||
feasible to modify or subclass this type to add a property
|
||||
to one's module. This means that programmers facing this
|
||||
API design decision, where the data-like member is a singleton
|
||||
stored in a module, must preemptively add ugly "getters"
|
||||
and "setters" for the data.
|
||||
|
||||
Adding support for module properties in pure Python is possible
|
||||
only by using hacks like:
|
||||
|
||||
* peeking in ``sys.getframe()``,
|
||||
|
||||
* changing the type of an object after it's created, or
|
||||
|
||||
* replacing the object stored in ``sys.modules``.
|
||||
|
||||
These techniques can be made to work, but they're fragile.
|
||||
|
||||
This PEP proposes a per-type opt-in extension to the descriptor
|
||||
protocol specifically designed to enable properties in modules.
|
||||
The mechanism is a way to honor the descriptor protocol for
|
||||
members of *instances* of a class without the member being declared
|
||||
as a class variable.
|
||||
|
||||
Although this is being proposed as a general mechanism, the author
|
||||
currently only forsees this as being useful for module objects.
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
The basic idea is simple: modify the ``tp_descr_get`` and ``tp_descr_set``
|
||||
functions exposed by ``PyModule_Type`` to inspect the attribute interacted
|
||||
with, and if it supports the descriptor protocol, call the relevant
|
||||
exposed function.
|
||||
|
||||
Our implementation faces two challenges:
|
||||
|
||||
1. Since this code will be run every time an attribute is looked up on a
|
||||
method, it needs to add very little overhead in the general case,
|
||||
where the object stored in the attribute is not a descriptor.
|
||||
|
||||
2. Since functions are descriptors, we must take care to *not* honor
|
||||
the descriptor protocol for all objects. Otherwise, all module-level
|
||||
functions will suddenly become bound to the module instance as if
|
||||
they were method calls on the module object. The module handle would
|
||||
be passed in as a "self" argument to all module-level functions.
|
||||
|
||||
Both challenges can be solved with the same approach: we define a new
|
||||
"fast subclass" flag that means "This object is a desciptor, and it
|
||||
should be honored directly when this object is looked up as an
|
||||
attribute of an instance". So far the only placed where this flag
|
||||
is set is on ``PyProperty_Type``.
|
||||
|
||||
Prototype
|
||||
---------
|
||||
|
||||
A prototype of this functionality is under development
|
||||
at GitHub [github]_.
|
||||
|
||||
Acknowledgements
|
||||
----------------
|
||||
|
||||
Armin Rigo essentially proposed this mechanism when presented
|
||||
with the idea of "module properties", and educated the author
|
||||
both on the complexities of the problem and the proper solution.
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
.. [github]
|
||||
https://github.com/larryhastings/cpython/tree/module-properties
|
||||
|
||||
Copyright
|
||||
---------
|
||||
|
||||
This document has been placed in the public domain.
|
||||
|
||||
|
||||
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
fill-column: 70
|
||||
End:
|
Loading…
Reference in New Issue