[Python-checkins] r54989 - peps/trunk/pep-3119.txt peps/trunk/pep-3141.txt
guido.van.rossum
python-checkins at python.org
Fri Apr 27 00:33:28 CEST 2007
Author: guido.van.rossum
Date: Fri Apr 27 00:33:22 2007
New Revision: 54989
Modified:
peps/trunk/pep-3119.txt
peps/trunk/pep-3141.txt
Log:
PEP 3141: Fix spelling of Transcendental.
PEP 3119: Add overloading isinstance() and issubclass();
tighten invariant for Mapping.keys/values/items to use list().
Modified: peps/trunk/pep-3119.txt
==============================================================================
--- peps/trunk/pep-3119.txt (original)
+++ peps/trunk/pep-3119.txt Fri Apr 27 00:33:22 2007
@@ -20,6 +20,8 @@
can be used to define abstract methods. A class containing an
abstract method that isn't overridden cannot be instantiated.
+* A way to overload ``isinstance()`` and ``issubclass()``.
+
* Specific ABCs for containers and iterators, to be added to the
collections module.
@@ -124,6 +126,8 @@
* An "ABC support framework" which defines a built-in decorator that
make it easy to define ABCs, and mechanisms to support it.
+* A way to overload ``isinstance()`` and ``issubclass()``.
+
* Specific ABCs for containers and iterators, to be added to the
collections module.
@@ -180,6 +184,76 @@
cooperative multiple-inheritance [7]_, [8]_.
+Overloading ``isinstance()`` and ``issubclass()``
+-------------------------------------------------
+
+During the development of this PEP and of its companion, PEP 3141, we
+repeatedly faced the choice between standardizing more, fine-grained
+ABCs or fewer, course-grained ones. For example, at one stage, PEP
+3141 introduced the following stack of base classes used for complex
+numbers: MonoidUnderPlus, AdditiveGroup, Ring, Field, Complex (each
+derived from the previous). And the discussion mentioned several
+other algebraic categorizations that were left out: Algebraic,
+Transcendental, and IntegralDomain, and PrincipalIdealDomain. In this
+PEP, we are wondering about the use cases for separate classes like
+Set, ComposableSet, MutableSet, HashableSet, MutableComposableSet,
+HashableComposableSet.
+
+The dilemma here is that we'd rather have fewer ABCs, but then what
+should a user do who needs a less refined ABC? Consider e.g. the
+plight of a mathematician who wants to define his own kind of
+Transcendental numbers, but also wants float and int to be considered
+Transcendental. PEP 3141 originally proposed to patch float.__bases__
+for that purpose, but there are some good reasons to keep the built-in
+types immutable (for one, they are shared between all Python
+interpreters running in the same address space, as is used by
+mod_python).
+
+The solution proposed here is to allow overloading the built-in
+functions ``isinstance()`` and ``issubclass()``. The overloading
+works as follows: The call ``isinstance(x, C)`` first checks whether
+``C.__instancecheck__`` exists, and if so, calls
+``C.__subclasscheck__(x)`` instead of its normal implementation.
+Similarly, the call ``issubclass(D, C)`` first checks whether
+``C.__subclasscheck__`` exists, and if so, calls
+``C.__subclasscheck__(D)`` instead of its normal implementation.
+
+Note that the magic names are not ``__isinstance__`` and
+``__issubclass__``; this is because the reversal of the arguments
+could cause confusion, especially for the ``issubclass()`` overloader.
+
+(We could also provide a default implementation of these that
+implements the old algorithms; this would be more regular but would
+have additional backwards compatibility issues, since the old
+algorithms special-case objects not deriving from ``type`` in order to
+support a different kind of overloading of these operations.)
+
+A prototype implementation of this is given in [12]_.
+
+Here is an example with (very simple) implementations of
+``__instancecheck__`` and ``__subclasscheck__``::
+
+ assert issubclass(set, HashableSet) # Assume this is given
+
+ class ABC:
+
+ def __instancecheck__(cls, inst):
+ """Implement isinstance(inst, cls)."""
+ return any(cls.__subclasscheck__(c)
+ for c in {type(inst), inst.__class__})
+
+ def __subclasscheck__(cls, sub):
+ """Implement issubclass(sub, cls)."""
+ candidates = cls.__dict__.get("__subclass__", set()) | {cls}
+ return any(c in candidates for c in sub.mro())
+
+ class NoncomposableHashableSet(Set, Hashable, metaclass=ABC):
+ __subclass__ = {HashableSet}
+
+ assert issubclass(set, NoncomposableHashableSet)
+ assert isinstance({1, 2, 3}, NoncomposableHashableSet)
+
+
ABCs for Containers and Iterators
---------------------------------
@@ -514,12 +588,10 @@
The following invariant should hold for any mapping ``m``::
- set(m.items()) == set(zip(m.keys(), m.values()))
+ list(m.items()) == list(zip(m.keys(), m.values()))
- i.e. iterating over the keys and the values in parallel should
- return *corresponding* keys and values. **Open issues:** Should
- this always be required? How about the stronger invariant using
- ``list()`` instead of ``set()``?
+ i.e. iterating over the items, keys and values should return
+ results in the same order.
``HashableMapping``
A subclass of ``Mapping`` and ``Hashable``. The values should be
@@ -743,6 +815,9 @@
.. [11] Finite set, in Wikipedia
(http://en.wikipedia.org/wiki/Finite_set)
+.. [12] Make isinstance/issubclass overloadable
+ (http://python.org/sf/1708353)
+
Copyright
=========
Modified: peps/trunk/pep-3141.txt
==============================================================================
--- peps/trunk/pep-3141.txt (original)
+++ peps/trunk/pep-3141.txt Fri Apr 27 00:33:22 2007
@@ -237,7 +237,7 @@
algebraic, but Python does define these operations on floats,
which makes defining this class somewhat difficult.
-``Trancendental``
+``Transcendental``
The elementary functions
(http://en.wikipedia.org/wiki/Elementary_function) are
defined. These are basically arbitrary powers, trig functions, and
More information about the Python-checkins
mailing list