Merge branch 'master' of github.com:python/peps

This commit is contained in:
Barry Warsaw 2017-09-05 13:42:58 -07:00
commit 952c4b8601
3 changed files with 608 additions and 599 deletions

View File

@ -1,7 +1,5 @@
PEP: 12 PEP: 12
Title: Sample reStructuredText PEP Template Title: Sample reStructuredText PEP Template
Version: $Revision$
Last-Modified: $Date$
Author: David Goodger <goodger@python.org>, Author: David Goodger <goodger@python.org>,
Barry Warsaw <barry@python.org> Barry Warsaw <barry@python.org>
Status: Active Status: Active

File diff suppressed because it is too large Load Diff

View File

@ -11,95 +11,95 @@ Post-History: 4-Sep-2017
Abstract Abstract
-------- ========
Python's descriptor protocol requires that descriptors Python's descriptor protocol requires that descriptors
be members of the *type* of an object. This PEP proposes be members of the *type* of an object. This PEP proposes
an extension to the descriptor protocol allowing use of an extension to the descriptor protocol allowing use of
the descriptor protocol for members of *instances.* This the descriptor protocol for members of *instances.* This
would permit using properties in modules. would permit using properties in modules.
Rationale Rationale
--------- =========
Python's descriptor protocol guides programmers towards Python's descriptor protocol guides programmers towards
elegant API design. If your class supports a data-like elegant API design. If your class supports a data-like
member, and you *might* someday need to run code when member, and you *might* someday need to run code when
changing the member's value, you're encouraged to changing the member's value, you're encouraged to
simply declare it as a simple data member of the class simply declare it as a simple data member of the class
for now. If in the future you do need to run code, you 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 can change it to a "property", and happily the API doesn't
change. change.
Unfortunately this doesn't work with modules. Modules are Unfortunately this doesn't work with modules. Modules are
instances of a single generic ``module`` type, and it's not instances of a single generic ``module`` type, and it's not
feasible to modify or subclass this type to add a property feasible to modify or subclass this type to add a property
to one's module. This means that programmers facing this to one's module. This means that programmers facing this
API design decision, where the data-like member is a singleton API design decision, where the data-like member is a singleton
stored in a module, must preemptively add ugly "getters" stored in a module, must preemptively add ugly "getters"
and "setters" for the data. and "setters" for the data.
Adding support for module properties in pure Python is possible Adding support for module properties in pure Python is possible
only by using hacks like: only by using hacks like:
* peeking in ``sys.getframe()``, * peeking in ``sys.getframe()``,
* changing the type of an object after it's created, or * changing the type of an object after it's created, or
* replacing the object stored in ``sys.modules``. * replacing the object stored in ``sys.modules``.
These techniques can be made to work, but they're fragile. These techniques can be made to work, but they're fragile.
This PEP proposes a per-type opt-in extension to the descriptor This PEP proposes a per-type opt-in extension to the descriptor
protocol specifically designed to enable properties in modules. protocol specifically designed to enable properties in modules.
The mechanism is a way to honor the descriptor protocol for The mechanism is a way to honor the descriptor protocol for
members of *instances* of a class without the member being declared members of *instances* of a class without the member being declared
as a class variable. as a class variable.
Although this is being proposed as a general mechanism, the author Although this is being proposed as a general mechanism, the author
currently only forsees this as being useful for module objects. currently only forsees this as being useful for module objects.
Implementation Implementation
-------------- ==============
The basic idea is simple: modify the ``tp_descr_get`` and ``tp_descr_set`` The basic idea is simple: modify the ``tp_descr_get`` and ``tp_descr_set``
functions exposed by ``PyModule_Type`` to inspect the attribute interacted functions exposed by ``PyModule_Type`` to inspect the attribute interacted
with, and if it supports the descriptor protocol, call the relevant with, and if it supports the descriptor protocol, call the relevant
exposed function. exposed function.
Our implementation faces two challenges: Our implementation faces two challenges:
1. Since this code will be run every time an attribute is looked up on a 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, method, it needs to add very little overhead in the general case,
where the object stored in the attribute is not a descriptor. where the object stored in the attribute is not a descriptor.
2. Since functions are descriptors, we must take care to *not* honor 2. Since functions are descriptors, we must take care to *not* honor
the descriptor protocol for all objects. Otherwise, all module-level the descriptor protocol for all objects. Otherwise, all module-level
functions will suddenly become bound to the module instance as if functions will suddenly become bound to the module instance as if
they were method calls on the module object. The module handle would they were method calls on the module object. The module handle would
be passed in as a "self" argument to all module-level functions. 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 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 "fast subclass" flag that means "This object is a desciptor, and it
should be honored directly when this object is looked up as an should be honored directly when this object is looked up as an
attribute of an instance". So far the only placed where this flag attribute of an instance". So far the only placed where this flag
is set is on ``PyProperty_Type``. is set is on ``PyProperty_Type``.
Prototype Prototype
--------- =========
A prototype of this functionality is under development A prototype of this functionality is under development
at GitHub [github]_. at GitHub [github]_.
Acknowledgements Acknowledgements
---------------- ================
Armin Rigo essentially proposed this mechanism when presented Armin Rigo essentially proposed this mechanism when presented
with the idea of "module properties", and educated the author with the idea of "module properties", and educated the author
both on the complexities of the problem and the proper solution. both on the complexities of the problem and the proper solution.
References References
---------- ==========
.. [github] .. [github]
https://github.com/larryhastings/cpython/tree/module-properties https://github.com/larryhastings/cpython/tree/module-properties
@ -107,7 +107,7 @@ References
Copyright Copyright
--------- ---------
This document has been placed in the public domain. This document has been placed in the public domain.