reSTify PEP 205 (#369)

This commit is contained in:
Huang Huang 2017-09-13 07:27:44 +08:00 committed by Guido van Rossum
parent a49551d35b
commit d80d5be223
1 changed files with 350 additions and 333 deletions

View File

@ -5,17 +5,20 @@ Last-Modified: $Date$
Author: Fred L. Drake, Jr. <fdrake@acm.org>
Status: Final
Type: Standards Track
Content-Type: text/x-rst
Created:
Python-Version: 2.1
Post-History: 11-Jan-2001
Motivation
==========
There are two basic applications for weak references which have
been noted by Python programmers: object caches and reduction of
pain from circular references.
Caches (weak dictionaries)
--------------------------
There is a need to allow objects to be maintained that represent
external state, mapping a single instance to the external
@ -49,12 +52,13 @@ Motivation
individual objects will overlap in lifespan.
Circular references
-------------------
- DOMs require a huge amount of circular (to parent & document
nodes) references, but these could be eliminated using a weak
dictionary mapping from each node to its parent. This
might be especially useful in the context of something like
xml.dom.pulldom, allowing the .unlink() operation to become
``xml.dom.pulldom``, allowing the ``.unlink()`` operation to become
a no-op.
This proposal is divided into the following sections:
@ -70,13 +74,15 @@ Motivation
Aspects of the Solution Space
=============================
There are two distinct aspects to the weak references problem:
- Invalidation of weak references
- Presentation of weak references to Python code
Invalidation:
Invalidation
------------
Past approaches to weak reference invalidation have often hinged
on storing a strong reference and being able to examine all the
@ -109,7 +115,8 @@ Aspects of the Solution Space
map from an object to a chain of weak references for that object
is needed as well.
Presentation:
Presentation
------------
Two ways that weak references are presented to the Python layer
have been as explicit reference objects upon which some operation
@ -128,6 +135,7 @@ Aspects of the Solution Space
Proposed Solution
=================
Weak references should be able to point to any Python object that
may have substantial memory size (directly or indirectly), or hold
@ -135,10 +143,10 @@ Proposed Solution
files, etc.).
A new module, weakref, will contain new functions used to create
weak references. weakref.ref() will create a "weak reference
weak references. ``weakref.ref()`` will create a "weak reference
object" and optionally attach a callback which will be called when
the object is about to be finalized. weakref.mapping() will
create a "weak dictionary". A third function, weakref.proxy(),
the object is about to be finalized. ``weakref.mapping()`` will
create a "weak dictionary". A third function, ``weakref.proxy()``,
will create a proxy object that behaves somewhat like the original
object.
@ -164,7 +172,7 @@ Proposed Solution
be compared once the referent has expired, and comparability is
necessary for dictionary keys. Operations on proxy objects after
the referent dies cause weakref.ReferenceError to be raised in
most cases. "is" comparisons, type(), and id() will continue to
most cases. "is" comparisons, ``type()``, and ``id()`` will continue to
work, but always refer to the proxy and not the referent.
The callbacks registered with weak references must accept a single
@ -174,6 +182,7 @@ Proposed Solution
Implementation Strategy
=======================
The implementation of weak references will include a list of
reference containers that must be cleared for each weakly-
@ -188,9 +197,9 @@ Implementation Strategy
structure will contain an additional field which provides an
offset into the instance structure which contains a list of weak
reference structures. If the value of the field is <= 0, the
object does not participate. In this case, weakref.ref(),
<weakdict>.__setitem__() and .setdefault(), and item assignment will
raise TypeError. If the value of the field is > 0, a new weak
object does not participate. In this case, ``weakref.ref()``,
``<weakdict>.__setitem__()`` and ``.setdefault()``, and item assignment will
raise ``TypeError``. If the value of the field is > 0, a new weak
reference can be generated and added to the list.
This approach is taken to allow arbitrary extension types to
@ -202,18 +211,19 @@ Implementation Strategy
class types ("new-style classes") in Python 2.2, types grew
support for weak references. Instances of class types are weakly
referencable if they have a base type which is weakly referencable,
the class not specify __slots__, or a slot is named __weakref__.
the class not specify ``__slots__``, or a slot is named ``__weakref__``.
Generators also support weak references.
Possible Applications
=====================
PyGTK+ bindings?
Tkinter -- could avoid circular references by using weak
references from widgets to their parents. Objects won't be
discarded any sooner in the typical case, but there won't be so
much dependence on the programmer calling .destroy() before
much dependence on the programmer calling ``.destroy()`` before
releasing a reference. This would mostly benefit long-running
applications.
@ -221,6 +231,7 @@ Possible Applications
Previous Weak Reference Work in Python
======================================
Dianne Hackborn has proposed something called "virtual references".
'vref' objects are very similar to java.lang.ref.WeakReference
@ -251,6 +262,7 @@ Previous Weak Reference Work in Python
Weak References in Java
=======================
http://java.sun.com/j2se/1.3/docs/api/java/lang/ref/package-summary.html
@ -286,27 +298,29 @@ Weak References in Java
released. The "soft" reference does own a reference, but allows
the memory allocator to free the referent if the memory is needed
elsewhere. It is not clear whether this means soft references are
released before the malloc() implementation calls sbrk() or its
equivalent, or if soft references are only cleared when malloc()
returns NULL.
released before the ``malloc()`` implementation calls ``sbrk()`` or its
equivalent, or if soft references are only cleared when ``malloc()``
returns ``NULL``.
"Phantom" references are a little different; unlike weak and soft
references, the referent is not cleared when the reference is
added to its queue. When all phantom references for an object
are dequeued, the object is cleared. This can be used to keep an
object alive until some additional cleanup is performed which
needs to happen before the objects .finalize() method is called.
needs to happen before the objects ``.finalize()`` method is called.
Unlike the other two reference types, "phantom" references must be
associated with an invalidation queue.
Appendix -- Dianne Hackborn's vref proposal (1995)
==================================================
[This has been indented and paragraphs reflowed, but there have be
no content changes. --Fred]
Proposal: Virtual References
----------------------------
In an attempt to partly address the recurring discussion
concerning reference counting vs. garbage collection, I would like
@ -340,7 +354,7 @@ Appendix -- Dianne Hackborn's vref proposal (1995)
doubly-linked list, which is used below.
2. The addition of a new field to the basic Python object
[PyObject_Head in object.h], which is either NULL, or points to
[``PyObject_Head`` in object.h], which is either ``NULL``, or points to
the head of a list of all vref objects that reference it. When
a vref object attaches itself to another object, it adds itself
to this linked list. Then, if an object with any vrefs on it
@ -350,13 +364,14 @@ Appendix -- Dianne Hackborn's vref proposal (1995)
This implementation should hopefully have a minimal impact on the
current Python core -- when no vrefs exist, it should only add one
pointer to all objects, and a check for a NULL pointer every time
pointer to all objects, and a check for a ``NULL`` pointer every time
an object is deallocated.
Back at the Python language level, I have considered two possible
semantics for the vref object --
==> Pointer semantics:
Pointer semantics
-----------------
In this model, a vref behaves essentially like a Python-level
pointer; the Python program must explicitly dereference the vref
@ -364,16 +379,16 @@ Appendix -- Dianne Hackborn's vref proposal (1995)
An example vref module using this model could include the
function "new"; When used as 'MyVref = vref.new(MyObject)', it
returns a new vref object such that MyVref.object ==
MyObject. MyVref.object would then change to Nothing if
MyObject is ever deallocated.
returns a new vref object such that ``MyVref.object == MyObject``.
``MyVref.object`` would then change to Nothing if
``MyObject`` is ever deallocated.
For a concrete example, we may introduce some new C-style syntax:
& -- unary operator, creates a vref on an object, same as vref.new().
* -- unary operator, dereference a vref, same as VrefObject.object.
* ``&`` -- unary operator, creates a vref on an object, same as ``vref.new()``.
* ``*`` -- unary operator, dereference a vref, same as ``VrefObject.object``.
We can then define:
We can then define::
1. type(&MyObject) == vref.VrefType
2. *(&MyObject) == MyObject
@ -385,14 +400,15 @@ Appendix -- Dianne Hackborn's vref proposal (1995)
to (a vref with no real references). Thus the outer vref is
cleared to Nothing when the inner one inevitably disappears.
==> Proxy semantics:
Proxy semantics
----------------
In this model, the Python programmer manipulates vref objects
just as if she were manipulating the object it is a reference
of. This is accomplished by implementing the vref so that all
operations on it are redirected to its referenced object. With
this model, the dereference operator (*) no longer makes sense;
instead, we have only the reference operator (&), and define:
instead, we have only the reference operator (&), and define::
1. type(&MyObject) == type(MyObject)
2. &MyObject == MyObject
@ -434,11 +450,12 @@ Appendix -- Dianne Hackborn's vref proposal (1995)
Copyright
=========
This document has been placed in the public domain.
..
Local Variables:
mode: indented-text
indent-tabs-mode: nil