Skip to content

Commit ac9a270

Browse files
committed
Deal with some open issues. Add some others. Will be posting soon.
1 parent fc624d8 commit ac9a270

File tree

1 file changed

+122
-69
lines changed

1 file changed

+122
-69
lines changed

pep-3119.txt

Lines changed: 122 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Status: Draft
77
Type: Standards Track
88
Content-Type: text/x-rst
99
Created: 18-Apr-2007
10-
Post-History: Not yet posted
10+
Post-History: 26-Apr-2007
1111

1212

1313
Abstract
@@ -213,19 +213,18 @@ These ABCs are closer to ``object`` in the ABC hierarchy.
213213
``PartiallyOrdered``
214214
This ABC defines the 4 inequality operations ``<``, ``<=``, ``>=``,
215215
``>``. (Note that ``==`` and ``!=`` are defined by ``object``.)
216-
Classes deriving from this ABC should satisfy weak invariants such
217-
as ``a < b < c`` implies ``a < c`` but don't require that for any
218-
two instances ``x`` and ``y`` exactly one of ``x < y``, ``x == y``
219-
or ``x >= y`` apply.
216+
Classes deriving from this ABC should implement a partial order
217+
as defined in mathematics. [9]_
220218

221219
``TotallyOrdered``
222220
This ABC derives from ``PartiallyOrdered``. It adds no new
223-
operations but implies a promise of stronger invariants. **Open
224-
issues:** Should ``float`` derive from ``TotallyOrdered`` even
225-
though for ``NaN`` this isn't strictly correct?
221+
operations but implies a promise of stronger invariants.
222+
Classes deriving from this ABC should implement a total order
223+
as defined in mathematics. [10]_
226224

227225
**Open issues:** Where should these live? The ``collections`` module
228-
doesn't seem right.
226+
doesn't seem right, but making them built-ins seems a slippery slope
227+
too.
229228

230229

231230
One Trick Ponies
@@ -252,7 +251,7 @@ These abstract classes represent single methods like ``__iter__`` or
252251
instances only, ``__hash__`` for those instances should raise a
253252
``TypeError`` exception.
254253

255-
Note: being an instance of this class does not imply that an
254+
**Note:** being an instance of this class does not imply that an
256255
object is immutable; e.g. a tuple containing a list as a member is
257256
not immutable; its ``__hash__`` method raises ``TypeError``.
258257

@@ -266,21 +265,15 @@ These abstract classes represent single methods like ``__iter__`` or
266265
The base class for classes defining ``__next__``. This derives
267266
from ``Iterable``. The abstract ``__next__`` method raises
268267
``StopIteration``. The concrete ``__iter__`` method returns
269-
``self``. (Note: this assumes PEP 3114 is implemented.)
268+
``self``.
270269

271270
``Sized``
272271
The base class for classes defining ``__len__``. The ``__len__``
273272
method should return an ``Integer`` (see "Numbers" below) >= 0.
274273
The abstract ``__len__`` method returns 0. **Invariant:** If a
275274
class ``C`` derives from ``Sized`` as well as from ``Iterable``,
276275
the invariant ``sum(1 for x in o) == len(o)`` should hold for any
277-
instance ``o`` of ``C``. **Open issues:** Is ``Sized`` the best
278-
name? Proposed alternatives already tentatively rejected:
279-
``Finite`` (nobody understood it), ``Lengthy``, ``Sizeable`` (both
280-
too cute), ``Countable`` (the set of natural numbers is a
281-
countable set in math), ``Enumerable`` (sounds like a sysnonym for
282-
``Iterable``), ``Dimension``, ``Extent`` (sound like numbers to
283-
me), ``Bounded`` (probably just as confusing as ``Fininte``).
276+
instance ``o`` of ``C``.
284277

285278
``Container``
286279
The base class for classes defining ``__contains__``. The
@@ -290,7 +283,7 @@ These abstract classes represent single methods like ``__iter__`` or
290283
``Iterable``, then ``(x in o for x in o)`` should be a generator
291284
yielding only True values for any instance ``o`` of ``C``.
292285

293-
Note: strictly speaking, there are three variants of this method's
286+
**Note:** strictly speaking, there are three variants of this method's
294287
semantics. The first one is for sets and mappings, which is fast:
295288
O(1) or O(log N). The second one is for membership checking on
296289
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.
337330
a set though! Sets have the additional invariant that each
338331
element occurs only once (as can be determined by iteration), and
339332
in addition sets define concrete operators that implement the
340-
inequality operations as subclass/superclass tests.
333+
inequality operations as subclass/superclass tests. In general,
334+
the invariants for finite sets in mathematics hold. [11]_
341335

342336
Sets with different implementations can be compared safely,
343-
efficiently and correctly. Because ``Set`` derives from
344-
``Sized``, ``__eq__`` takes a shortcut and returns ``False``
345-
immediately if two sets of unequal length are compared.
346-
Similarly, ``__le__`` returns ``False`` immediately if the first
347-
set has more members than the second set. Note that set inclusion
348-
implements only a partial ordering; e.g. ``{1, 2}`` and ``{1, 3}``
349-
are not ordered (all three of ``<``, ``==`` and ``>`` return
350-
``False`` for these arguments). Sets cannot be ordered relative
351-
to mappings or sequences, but they can be compared for equality
352-
(and then they always compare unequal).
353-
354-
Note: the ``issubset`` and ``issuperset`` methods found on the set
355-
type in Python 2 are not supported, as these are mostly just
337+
(usually) efficiently and correctly using the mathematical
338+
definitions of the subclass/superclass operations for finite sets.
339+
The ordering operations have concrete implementations; subclasses
340+
may override these for speed but should maintain the semantics.
341+
Because ``Set`` derives from ``Sized``, ``__eq__`` may take a
342+
shortcut and returns ``False`` immediately if two sets of unequal
343+
length are compared. Similarly, ``__le__`` may return ``False``
344+
immediately if the first set has more members than the second set.
345+
Note that set inclusion implements only a partial ordering;
346+
e.g. ``{1, 2}`` and ``{1, 3}`` are not ordered (all three of
347+
``<``, ``==`` and ``>`` return ``False`` for these arguments).
348+
Sets cannot be ordered relative to mappings or sequences, but they
349+
can be compared to those for equality (and then they always
350+
compare unequal).
351+
352+
**Note:** the ``issubset`` and ``issuperset`` methods found on the
353+
set type in Python 2 are not supported, as these are mostly just
356354
aliases for ``__le__`` and ``__ge__``.
357355

358-
**Open issues:** Spell out the invariants and method definitions.
356+
**Open issues:** should we define comparison of instances of
357+
different concrete set types this way?
359358

360359
``ComposableSet``
361360
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.
366365
``NotImplementedError``; this is because any generic
367366
implementation would have to create new instances but the ABCs
368367
don't (and shouldn't, IMO) provide an API for creating new
369-
instances. **Invariants:** The implementations of these operators
370-
should ensure that the results match the mathematical definition
371-
of set composition.
372-
373-
**Open issues:** Should I spell out the invariants? Should we
374-
define an API for creating new instances (e.g. a class method or a
375-
fixed constructor signature)? Should we just pick a concrete
376-
return type (e.g. ``set``)?
368+
instances. The implementations of these operators should ensure
369+
that the results match the mathematical definition of set
370+
composition. [11]_
371+
372+
**Open issues:** Should ``__or__`` and friends be abstract or
373+
concrete methods? Making them abstract means that every
374+
ComposableSet implementation must reimplement all of them. But
375+
making them concrete begs the question of the actual return type:
376+
since the ABC doesn't (and IMO shouldn't) define the constructor
377+
signature for subclasses, the concrete implementations in the ABC
378+
don't have an API to construct a new instance given an iterable.
379+
Perhaps the right choice is to have a static concrete factory
380+
function ``fromiterable`` which takes an iterable and returns
381+
a ``ComposableSet`` instance. Subclasses can override this and
382+
benefit from the default implementations of ``__or__`` etc.; or
383+
they can override ``__or__`` if they want to.
377384

378385
``HashableSet``
379386
This is a subclass of both ``ComposableSet`` and ``Hashable``. It
@@ -385,8 +392,8 @@ out of the scope of a pragmatic proposal like this.
385392
values for different types of numbers and strings.)
386393

387394
**Open issues:** Spell out the hash algorithm. Should there be
388-
another ABC that derives from Set and Hashable (but not from
389-
Composable)?
395+
another ABC that derives from Set and Hashable, but not from
396+
Composable?
390397

391398
``MutableSet``
392399
This is a subclass of ``ComposableSet`` implementing additional
@@ -421,7 +428,7 @@ out of the scope of a pragmatic proposal like this.
421428
``.clear()``
422429
Concrete method that empties the set. The default
423430
implementation repeatedly calls ``self.pop()`` until
424-
``KeyError`` is caught. (Note: this is probably much slower
431+
``KeyError`` is caught. (**Note:** this is likely much slower
425432
than simply creating a new set, even if an implementation
426433
overrides it with a faster approach; but in some cases object
427434
identity is important.)
@@ -467,21 +474,52 @@ The built-in type ``dict`` derives from ``MutableMapping``.
467474
raise ``KeyError``, and ``False`` if it does.
468475

469476
``Mapping``
470-
A subclass of ``BasicMapping``, ``iterable`` and ``Sized``. It
471-
defines concrete methods ``__eq__``, ``keys``, ``items``,
472-
``values``. Iterating over a mapping should return all the valid
473-
keys (i.e. those keys for which ``.__getitem__()`` returns a
474-
value), once each, and nothing else. The lengh of a mapping
475-
should equal to the number of elements returned by iterating over
476-
the object until the end of the iterator is reached (this is
477-
implied by the invariant listed above for ``Sized``). Two
478-
mappings, even with different implementations, can be compared for
479-
equality, and are considered equal if and only iff their items
480-
compare equal when converted to sets. The ``keys``, ``items`` and
481-
``values`` methods return views; ``keys`` and ``items`` return
482-
``Set`` views, ``values`` returns a ``Container`` view. The
483-
following invariant should hold: m.items() == set(zip(m.keys(),
484-
m.values())).
477+
A subclass of ``BasicMapping``, ``Iterable`` and ``Sized``. The
478+
keys of a mapping naturally form a set. The (key, value) pairs
479+
are also referred to as items. The items also form a set.
480+
Methods:
481+
482+
``__len__``
483+
Abstract method returning the length of the key set.
484+
485+
``__iter__``
486+
Abstract method returning each key in the key set exactly once.
487+
488+
``__eq__``
489+
Concrete method for comparing mappings. Two mappings, even
490+
with different implementations, can be compared for equality,
491+
and are considered equal if and only iff their item sets are
492+
equal. **Open issues:** should we define comparison of
493+
instances of different concrete mapping types this way?
494+
495+
``keys``
496+
Concrete method returning the key set as a ``Set``. The
497+
default concrete implementation returns a "view" on the key
498+
set (meaning if the underlying mapping is modified, the view's
499+
value changes correspondingly); subclasses are not required to
500+
return a view but they should return a ``Set``.
501+
502+
``items``
503+
Concrete method returning the items as a ``Set``. The default
504+
concrete implementation returns a "view" on the item set;
505+
subclasses are not required to return a view but they should
506+
return a ``Set``.
507+
508+
``values``
509+
Concrete method returning the values as a sized, iterable
510+
container (not a set!). The default concrete implementation
511+
returns a "view" on the values of the mapping; subclasses are
512+
not required to return a view but they should return a sized,
513+
iterable container.
514+
515+
The following invariant should hold for any mapping ``m``::
516+
517+
set(m.items()) == set(zip(m.keys(), m.values()))
518+
519+
i.e. iterating over the keys and the values in parallel should
520+
return *corresponding* keys and values. **Open issues:** Should
521+
this always be required? How about the stronger invariant using
522+
``list()`` instead of ``set()``?
485523

486524
``HashableMapping``
487525
A subclass of ``Mapping`` and ``Hashable``. The values should be
@@ -492,11 +530,8 @@ The built-in type ``dict`` derives from ``MutableMapping``.
492530
A subclass of ``Mapping`` that also implements some standard
493531
mutating methods. Abstract methods include ``__setitem__``,
494532
``__delitem__``. Concrete methods include ``pop``, ``popitem``,
495-
``clear``, ``update``. Note: ``setdefault`` is *not* included.
496-
497-
**Open issues:**
498-
499-
* We should say more about mapping view types.
533+
``clear``, ``update``. **Note:** ``setdefault`` is *not* included.
534+
**Open issues:** Write out the specs for the methods.
500535

501536

502537
Sequences
@@ -510,7 +545,7 @@ from ``HashableSequence``.
510545

511546
``Sequence``
512547
A subclass of ``Iterable``, ``Sized``, ``Container``. It
513-
defines a new abstract method ``__getitem__`` that has a
548+
defines a new abstract method ``__getitem__`` that has a somewhat
514549
complicated signature: when called with an integer, it returns an
515550
element of the sequence or raises ``IndexError``; when called with
516551
a ``slice`` object, it returns another ``Sequence``. The concrete
@@ -535,10 +570,19 @@ from ``HashableSequence``.
535570
well as slices), ``__delitem__`` (ditto), ``insert``, ``append``,
536571
``reverse``. Concrete mutating methods: ``extend``, ``pop``,
537572
``remove``. Concrete mutating operators: ``+=``, ``*=`` (these
538-
mutate the object in place). Note: this does not define
573+
mutate the object in place). **Note:** this does not define
539574
``sort()`` -- that is only required to exist on genuine ``list``
540575
instances.
541576

577+
**Open issues:** If all the elements of a sequence are totally
578+
ordered, the sequence itself can be totally ordered with respect to
579+
other sequences containing corresponding items of the same type.
580+
Should we reflect this by making ``Sequence`` derive from
581+
``TotallyOrdered``? Or ``Partiallyordered``? Also, we could easily
582+
define comparison of sequences of different types, so that e.g.
583+
``(1, 2, 3) == [1, 2, 3]`` and ``(1, 2) < [1, 2, 3]``. Should we?
584+
(It might imply ``["a", "b"] == "ab"`` and ``[1, 2] == b"\1\2"``.)
585+
542586

543587
Strings
544588
-------
@@ -686,10 +730,19 @@ References
686730
.. [7] Unifying types and classes in Python 2.2, by GvR
687731
(http://www.python.org/download/releases/2.2.3/descrintro/)
688732

689-
.. [8] "Putting Metaclasses to Work: A New Dimension in Object-Oriented
690-
Programming", by Ira R. Forman and Scott H. Danforth
733+
.. [8] Putting Metaclasses to Work: A New Dimension in Object-Oriented
734+
Programming, by Ira R. Forman and Scott H. Danforth
691735
(http://www.amazon.com/gp/product/0201433052)
692736

737+
.. [9] Partial order, in Wikipedia
738+
(http://en.wikipedia.org/wiki/Partial_order)
739+
740+
.. [10] Total order, in Wikipedia
741+
(http://en.wikipedia.org/wiki/Total_order)
742+
743+
.. [11] Finite set, in Wikipedia
744+
(http://en.wikipedia.org/wiki/Finite_set)
745+
693746

694747
Copyright
695748
=========

0 commit comments

Comments
 (0)