@@ -7,7 +7,7 @@ Status: Draft
7
7
Type: Standards Track
8
8
Content-Type: text/x-rst
9
9
Created: 18-Apr-2007
10
- Post-History: Not yet posted
10
+ Post-History: 26-Apr-2007
11
11
12
12
13
13
Abstract
@@ -213,19 +213,18 @@ These ABCs are closer to ``object`` in the ABC hierarchy.
213
213
``PartiallyOrdered``
214
214
This ABC defines the 4 inequality operations ``<``, ``<=``, ``>=``,
215
215
``>``. (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]_
220
218
221
219
``TotallyOrdered``
222
220
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]_
226
224
227
225
**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.
229
228
230
229
231
230
One Trick Ponies
@@ -252,7 +251,7 @@ These abstract classes represent single methods like ``__iter__`` or
252
251
instances only, ``__hash__`` for those instances should raise a
253
252
``TypeError`` exception.
254
253
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
256
255
object is immutable; e.g. a tuple containing a list as a member is
257
256
not immutable; its ``__hash__`` method raises ``TypeError``.
258
257
@@ -266,21 +265,15 @@ These abstract classes represent single methods like ``__iter__`` or
266
265
The base class for classes defining ``__next__``. This derives
267
266
from ``Iterable``. The abstract ``__next__`` method raises
268
267
``StopIteration``. The concrete ``__iter__`` method returns
269
- ``self``. (Note: this assumes PEP 3114 is implemented.)
268
+ ``self``.
270
269
271
270
``Sized``
272
271
The base class for classes defining ``__len__``. The ``__len__``
273
272
method should return an ``Integer`` (see "Numbers" below) >= 0.
274
273
The abstract ``__len__`` method returns 0. **Invariant:** If a
275
274
class ``C`` derives from ``Sized`` as well as from ``Iterable``,
276
275
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``.
284
277
285
278
``Container``
286
279
The base class for classes defining ``__contains__``. The
@@ -290,7 +283,7 @@ These abstract classes represent single methods like ``__iter__`` or
290
283
``Iterable``, then ``(x in o for x in o)`` should be a generator
291
284
yielding only True values for any instance ``o`` of ``C``.
292
285
293
- Note: strictly speaking, there are three variants of this method's
286
+ ** Note:** strictly speaking, there are three variants of this method's
294
287
semantics. The first one is for sets and mappings, which is fast:
295
288
O(1) or O(log N). The second one is for membership checking on
296
289
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.
337
330
a set though! Sets have the additional invariant that each
338
331
element occurs only once (as can be determined by iteration), and
339
332
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]_
341
335
342
336
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
356
354
aliases for ``__le__`` and ``__ge__``.
357
355
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?
359
358
360
359
``ComposableSet``
361
360
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.
366
365
``NotImplementedError``; this is because any generic
367
366
implementation would have to create new instances but the ABCs
368
367
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.
377
384
378
385
``HashableSet``
379
386
This is a subclass of both ``ComposableSet`` and ``Hashable``. It
@@ -385,8 +392,8 @@ out of the scope of a pragmatic proposal like this.
385
392
values for different types of numbers and strings.)
386
393
387
394
**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?
390
397
391
398
``MutableSet``
392
399
This is a subclass of ``ComposableSet`` implementing additional
@@ -421,7 +428,7 @@ out of the scope of a pragmatic proposal like this.
421
428
``.clear()``
422
429
Concrete method that empties the set. The default
423
430
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
425
432
than simply creating a new set, even if an implementation
426
433
overrides it with a faster approach; but in some cases object
427
434
identity is important.)
@@ -467,21 +474,52 @@ The built-in type ``dict`` derives from ``MutableMapping``.
467
474
raise ``KeyError``, and ``False`` if it does.
468
475
469
476
``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()``?
485
523
486
524
``HashableMapping``
487
525
A subclass of ``Mapping`` and ``Hashable``. The values should be
@@ -492,11 +530,8 @@ The built-in type ``dict`` derives from ``MutableMapping``.
492
530
A subclass of ``Mapping`` that also implements some standard
493
531
mutating methods. Abstract methods include ``__setitem__``,
494
532
``__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.
500
535
501
536
502
537
Sequences
@@ -510,7 +545,7 @@ from ``HashableSequence``.
510
545
511
546
``Sequence``
512
547
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
514
549
complicated signature: when called with an integer, it returns an
515
550
element of the sequence or raises ``IndexError``; when called with
516
551
a ``slice`` object, it returns another ``Sequence``. The concrete
@@ -535,10 +570,19 @@ from ``HashableSequence``.
535
570
well as slices), ``__delitem__`` (ditto), ``insert``, ``append``,
536
571
``reverse``. Concrete mutating methods: ``extend``, ``pop``,
537
572
``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
539
574
``sort()`` -- that is only required to exist on genuine ``list``
540
575
instances.
541
576
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
+
542
586
543
587
Strings
544
588
-------
@@ -686,10 +730,19 @@ References
686
730
.. [7] Unifying types and classes in Python 2.2, by GvR
687
731
(http://www.python.org/download/releases/2.2.3/descrintro/)
688
732
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
691
735
(http://www.amazon.com/gp/product/0201433052)
692
736
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
+
693
746
694
747
Copyright
695
748
=========
0 commit comments