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
Title: Sample reStructuredText PEP Template
Version: $Revision$
Last-Modified: $Date$
Author: David Goodger <goodger@python.org>,
Barry Warsaw <barry@python.org>
Status: Active

File diff suppressed because it is too large Load Diff

View File

@ -11,95 +11,95 @@ 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.
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.
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.
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:
Adding support for module properties in pure Python is possible
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
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.
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.
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.
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:
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.
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.
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``.
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]_.
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.
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
@ -107,7 +107,7 @@ References
Copyright
---------
This document has been placed in the public domain.
This document has been placed in the public domain.