Deal with some open issues. Add some others. Will be posting soon.

This commit is contained in:
Guido van Rossum 2007-04-26 18:24:07 +00:00
parent fc624d8d81
commit ac9a2701b5
1 changed files with 120 additions and 67 deletions

View File

@ -7,7 +7,7 @@ Status: Draft
Type: Standards Track Type: Standards Track
Content-Type: text/x-rst Content-Type: text/x-rst
Created: 18-Apr-2007 Created: 18-Apr-2007
Post-History: Not yet posted Post-History: 26-Apr-2007
Abstract Abstract
@ -213,19 +213,18 @@ These ABCs are closer to ``object`` in the ABC hierarchy.
``PartiallyOrdered`` ``PartiallyOrdered``
This ABC defines the 4 inequality operations ``<``, ``<=``, ``>=``, This ABC defines the 4 inequality operations ``<``, ``<=``, ``>=``,
``>``. (Note that ``==`` and ``!=`` are defined by ``object``.) ``>``. (Note that ``==`` and ``!=`` are defined by ``object``.)
Classes deriving from this ABC should satisfy weak invariants such Classes deriving from this ABC should implement a partial order
as ``a < b < c`` implies ``a < c`` but don't require that for any as defined in mathematics. [9]_
two instances ``x`` and ``y`` exactly one of ``x < y``, ``x == y``
or ``x >= y`` apply.
``TotallyOrdered`` ``TotallyOrdered``
This ABC derives from ``PartiallyOrdered``. It adds no new This ABC derives from ``PartiallyOrdered``. It adds no new
operations but implies a promise of stronger invariants. **Open operations but implies a promise of stronger invariants.
issues:** Should ``float`` derive from ``TotallyOrdered`` even Classes deriving from this ABC should implement a total order
though for ``NaN`` this isn't strictly correct? as defined in mathematics. [10]_
**Open issues:** Where should these live? The ``collections`` module **Open issues:** Where should these live? The ``collections`` module
doesn't seem right. doesn't seem right, but making them built-ins seems a slippery slope
too.
One Trick Ponies One Trick Ponies
@ -252,7 +251,7 @@ These abstract classes represent single methods like ``__iter__`` or
instances only, ``__hash__`` for those instances should raise a instances only, ``__hash__`` for those instances should raise a
``TypeError`` exception. ``TypeError`` exception.
Note: being an instance of this class does not imply that an **Note:** being an instance of this class does not imply that an
object is immutable; e.g. a tuple containing a list as a member is object is immutable; e.g. a tuple containing a list as a member is
not immutable; its ``__hash__`` method raises ``TypeError``. not immutable; its ``__hash__`` method raises ``TypeError``.
@ -266,7 +265,7 @@ These abstract classes represent single methods like ``__iter__`` or
The base class for classes defining ``__next__``. This derives The base class for classes defining ``__next__``. This derives
from ``Iterable``. The abstract ``__next__`` method raises from ``Iterable``. The abstract ``__next__`` method raises
``StopIteration``. The concrete ``__iter__`` method returns ``StopIteration``. The concrete ``__iter__`` method returns
``self``. (Note: this assumes PEP 3114 is implemented.) ``self``.
``Sized`` ``Sized``
The base class for classes defining ``__len__``. The ``__len__`` The base class for classes defining ``__len__``. The ``__len__``
@ -274,13 +273,7 @@ These abstract classes represent single methods like ``__iter__`` or
The abstract ``__len__`` method returns 0. **Invariant:** If a The abstract ``__len__`` method returns 0. **Invariant:** If a
class ``C`` derives from ``Sized`` as well as from ``Iterable``, class ``C`` derives from ``Sized`` as well as from ``Iterable``,
the invariant ``sum(1 for x in o) == len(o)`` should hold for any the invariant ``sum(1 for x in o) == len(o)`` should hold for any
instance ``o`` of ``C``. **Open issues:** Is ``Sized`` the best instance ``o`` of ``C``.
name? Proposed alternatives already tentatively rejected:
``Finite`` (nobody understood it), ``Lengthy``, ``Sizeable`` (both
too cute), ``Countable`` (the set of natural numbers is a
countable set in math), ``Enumerable`` (sounds like a sysnonym for
``Iterable``), ``Dimension``, ``Extent`` (sound like numbers to
me), ``Bounded`` (probably just as confusing as ``Fininte``).
``Container`` ``Container``
The base class for classes defining ``__contains__``. The The base class for classes defining ``__contains__``. The
@ -290,7 +283,7 @@ These abstract classes represent single methods like ``__iter__`` or
``Iterable``, then ``(x in o for x in o)`` should be a generator ``Iterable``, then ``(x in o for x in o)`` should be a generator
yielding only True values for any instance ``o`` of ``C``. yielding only True values for any instance ``o`` of ``C``.
Note: strictly speaking, there are three variants of this method's **Note:** strictly speaking, there are three variants of this method's
semantics. The first one is for sets and mappings, which is fast: semantics. The first one is for sets and mappings, which is fast:
O(1) or O(log N). The second one is for membership checking on O(1) or O(log N). The second one is for membership checking on
sequences, which is slow: O(N). The third one is for subsequence sequences, which is slow: O(N). The third one is for subsequence
@ -337,25 +330,31 @@ out of the scope of a pragmatic proposal like this.
a set though! Sets have the additional invariant that each a set though! Sets have the additional invariant that each
element occurs only once (as can be determined by iteration), and element occurs only once (as can be determined by iteration), and
in addition sets define concrete operators that implement the in addition sets define concrete operators that implement the
inequality operations as subclass/superclass tests. inequality operations as subclass/superclass tests. In general,
the invariants for finite sets in mathematics hold. [11]_
Sets with different implementations can be compared safely, Sets with different implementations can be compared safely,
efficiently and correctly. Because ``Set`` derives from (usually) efficiently and correctly using the mathematical
``Sized``, ``__eq__`` takes a shortcut and returns ``False`` definitions of the subclass/superclass operations for finite sets.
immediately if two sets of unequal length are compared. The ordering operations have concrete implementations; subclasses
Similarly, ``__le__`` returns ``False`` immediately if the first may override these for speed but should maintain the semantics.
set has more members than the second set. Note that set inclusion Because ``Set`` derives from ``Sized``, ``__eq__`` may take a
implements only a partial ordering; e.g. ``{1, 2}`` and ``{1, 3}`` shortcut and returns ``False`` immediately if two sets of unequal
are not ordered (all three of ``<``, ``==`` and ``>`` return length are compared. Similarly, ``__le__`` may return ``False``
``False`` for these arguments). Sets cannot be ordered relative immediately if the first set has more members than the second set.
to mappings or sequences, but they can be compared for equality Note that set inclusion implements only a partial ordering;
(and then they always compare unequal). e.g. ``{1, 2}`` and ``{1, 3}`` are not ordered (all three of
``<``, ``==`` and ``>`` return ``False`` for these arguments).
Sets cannot be ordered relative to mappings or sequences, but they
can be compared to those for equality (and then they always
compare unequal).
Note: the ``issubset`` and ``issuperset`` methods found on the set **Note:** the ``issubset`` and ``issuperset`` methods found on the
type in Python 2 are not supported, as these are mostly just set type in Python 2 are not supported, as these are mostly just
aliases for ``__le__`` and ``__ge__``. aliases for ``__le__`` and ``__ge__``.
**Open issues:** Spell out the invariants and method definitions. **Open issues:** should we define comparison of instances of
different concrete set types this way?
``ComposableSet`` ``ComposableSet``
This is a subclass of ``Set`` that defines abstract operators to This is a subclass of ``Set`` that defines abstract operators to
@ -366,14 +365,22 @@ out of the scope of a pragmatic proposal like this.
``NotImplementedError``; this is because any generic ``NotImplementedError``; this is because any generic
implementation would have to create new instances but the ABCs implementation would have to create new instances but the ABCs
don't (and shouldn't, IMO) provide an API for creating new don't (and shouldn't, IMO) provide an API for creating new
instances. **Invariants:** The implementations of these operators instances. The implementations of these operators should ensure
should ensure that the results match the mathematical definition that the results match the mathematical definition of set
of set composition. composition. [11]_
**Open issues:** Should I spell out the invariants? Should we **Open issues:** Should ``__or__`` and friends be abstract or
define an API for creating new instances (e.g. a class method or a concrete methods? Making them abstract means that every
fixed constructor signature)? Should we just pick a concrete ComposableSet implementation must reimplement all of them. But
return type (e.g. ``set``)? making them concrete begs the question of the actual return type:
since the ABC doesn't (and IMO shouldn't) define the constructor
signature for subclasses, the concrete implementations in the ABC
don't have an API to construct a new instance given an iterable.
Perhaps the right choice is to have a static concrete factory
function ``fromiterable`` which takes an iterable and returns
a ``ComposableSet`` instance. Subclasses can override this and
benefit from the default implementations of ``__or__`` etc.; or
they can override ``__or__`` if they want to.
``HashableSet`` ``HashableSet``
This is a subclass of both ``ComposableSet`` and ``Hashable``. It This is a subclass of both ``ComposableSet`` and ``Hashable``. It
@ -385,8 +392,8 @@ out of the scope of a pragmatic proposal like this.
values for different types of numbers and strings.) values for different types of numbers and strings.)
**Open issues:** Spell out the hash algorithm. Should there be **Open issues:** Spell out the hash algorithm. Should there be
another ABC that derives from Set and Hashable (but not from another ABC that derives from Set and Hashable, but not from
Composable)? Composable?
``MutableSet`` ``MutableSet``
This is a subclass of ``ComposableSet`` implementing additional This is a subclass of ``ComposableSet`` implementing additional
@ -421,7 +428,7 @@ out of the scope of a pragmatic proposal like this.
``.clear()`` ``.clear()``
Concrete method that empties the set. The default Concrete method that empties the set. The default
implementation repeatedly calls ``self.pop()`` until implementation repeatedly calls ``self.pop()`` until
``KeyError`` is caught. (Note: this is probably much slower ``KeyError`` is caught. (**Note:** this is likely much slower
than simply creating a new set, even if an implementation than simply creating a new set, even if an implementation
overrides it with a faster approach; but in some cases object overrides it with a faster approach; but in some cases object
identity is important.) identity is important.)
@ -467,21 +474,52 @@ The built-in type ``dict`` derives from ``MutableMapping``.
raise ``KeyError``, and ``False`` if it does. raise ``KeyError``, and ``False`` if it does.
``Mapping`` ``Mapping``
A subclass of ``BasicMapping``, ``iterable`` and ``Sized``. It A subclass of ``BasicMapping``, ``Iterable`` and ``Sized``. The
defines concrete methods ``__eq__``, ``keys``, ``items``, keys of a mapping naturally form a set. The (key, value) pairs
``values``. Iterating over a mapping should return all the valid are also referred to as items. The items also form a set.
keys (i.e. those keys for which ``.__getitem__()`` returns a Methods:
value), once each, and nothing else. The lengh of a mapping
should equal to the number of elements returned by iterating over ``__len__``
the object until the end of the iterator is reached (this is Abstract method returning the length of the key set.
implied by the invariant listed above for ``Sized``). Two
mappings, even with different implementations, can be compared for ``__iter__``
equality, and are considered equal if and only iff their items Abstract method returning each key in the key set exactly once.
compare equal when converted to sets. The ``keys``, ``items`` and
``values`` methods return views; ``keys`` and ``items`` return ``__eq__``
``Set`` views, ``values`` returns a ``Container`` view. The Concrete method for comparing mappings. Two mappings, even
following invariant should hold: m.items() == set(zip(m.keys(), with different implementations, can be compared for equality,
m.values())). and are considered equal if and only iff their item sets are
equal. **Open issues:** should we define comparison of
instances of different concrete mapping types this way?
``keys``
Concrete method returning the key set as a ``Set``. The
default concrete implementation returns a "view" on the key
set (meaning if the underlying mapping is modified, the view's
value changes correspondingly); subclasses are not required to
return a view but they should return a ``Set``.
``items``
Concrete method returning the items as a ``Set``. The default
concrete implementation returns a "view" on the item set;
subclasses are not required to return a view but they should
return a ``Set``.
``values``
Concrete method returning the values as a sized, iterable
container (not a set!). The default concrete implementation
returns a "view" on the values of the mapping; subclasses are
not required to return a view but they should return a sized,
iterable container.
The following invariant should hold for any mapping ``m``::
set(m.items()) == set(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()``?
``HashableMapping`` ``HashableMapping``
A subclass of ``Mapping`` and ``Hashable``. The values should be A subclass of ``Mapping`` and ``Hashable``. The values should be
@ -492,11 +530,8 @@ The built-in type ``dict`` derives from ``MutableMapping``.
A subclass of ``Mapping`` that also implements some standard A subclass of ``Mapping`` that also implements some standard
mutating methods. Abstract methods include ``__setitem__``, mutating methods. Abstract methods include ``__setitem__``,
``__delitem__``. Concrete methods include ``pop``, ``popitem``, ``__delitem__``. Concrete methods include ``pop``, ``popitem``,
``clear``, ``update``. Note: ``setdefault`` is *not* included. ``clear``, ``update``. **Note:** ``setdefault`` is *not* included.
**Open issues:** Write out the specs for the methods.
**Open issues:**
* We should say more about mapping view types.
Sequences Sequences
@ -510,7 +545,7 @@ from ``HashableSequence``.
``Sequence`` ``Sequence``
A subclass of ``Iterable``, ``Sized``, ``Container``. It A subclass of ``Iterable``, ``Sized``, ``Container``. It
defines a new abstract method ``__getitem__`` that has a defines a new abstract method ``__getitem__`` that has a somewhat
complicated signature: when called with an integer, it returns an complicated signature: when called with an integer, it returns an
element of the sequence or raises ``IndexError``; when called with element of the sequence or raises ``IndexError``; when called with
a ``slice`` object, it returns another ``Sequence``. The concrete a ``slice`` object, it returns another ``Sequence``. The concrete
@ -535,10 +570,19 @@ from ``HashableSequence``.
well as slices), ``__delitem__`` (ditto), ``insert``, ``append``, well as slices), ``__delitem__`` (ditto), ``insert``, ``append``,
``reverse``. Concrete mutating methods: ``extend``, ``pop``, ``reverse``. Concrete mutating methods: ``extend``, ``pop``,
``remove``. Concrete mutating operators: ``+=``, ``*=`` (these ``remove``. Concrete mutating operators: ``+=``, ``*=`` (these
mutate the object in place). Note: this does not define mutate the object in place). **Note:** this does not define
``sort()`` -- that is only required to exist on genuine ``list`` ``sort()`` -- that is only required to exist on genuine ``list``
instances. instances.
**Open issues:** If all the elements of a sequence are totally
ordered, the sequence itself can be totally ordered with respect to
other sequences containing corresponding items of the same type.
Should we reflect this by making ``Sequence`` derive from
``TotallyOrdered``? Or ``Partiallyordered``? Also, we could easily
define comparison of sequences of different types, so that e.g.
``(1, 2, 3) == [1, 2, 3]`` and ``(1, 2) < [1, 2, 3]``. Should we?
(It might imply ``["a", "b"] == "ab"`` and ``[1, 2] == b"\1\2"``.)
Strings Strings
------- -------
@ -686,10 +730,19 @@ References
.. [7] Unifying types and classes in Python 2.2, by GvR .. [7] Unifying types and classes in Python 2.2, by GvR
(http://www.python.org/download/releases/2.2.3/descrintro/) (http://www.python.org/download/releases/2.2.3/descrintro/)
.. [8] "Putting Metaclasses to Work: A New Dimension in Object-Oriented .. [8] Putting Metaclasses to Work: A New Dimension in Object-Oriented
Programming", by Ira R. Forman and Scott H. Danforth Programming, by Ira R. Forman and Scott H. Danforth
(http://www.amazon.com/gp/product/0201433052) (http://www.amazon.com/gp/product/0201433052)
.. [9] Partial order, in Wikipedia
(http://en.wikipedia.org/wiki/Partial_order)
.. [10] Total order, in Wikipedia
(http://en.wikipedia.org/wiki/Total_order)
.. [11] Finite set, in Wikipedia
(http://en.wikipedia.org/wiki/Finite_set)
Copyright Copyright
========= =========