Fix typos and nits reported by various correspondents,
add a few clarifications and new open issues. Only the easy stuff.
This commit is contained in:
parent
43d62602d0
commit
e432788d3f
75
pep-3119.txt
75
pep-3119.txt
|
@ -183,6 +183,11 @@ may have an implementation. This implementation can be called via the
|
|||
useful as an end-point for a super-call in framework using a
|
||||
cooperative multiple-inheritance [7]_, [8]_.
|
||||
|
||||
**Open issues:** Should we also provide a standard way to declare
|
||||
abstract data attributes? If so, how should these be spelled?
|
||||
Perhaps place ``@abstractattribute`` decorators on properties? Or use
|
||||
an ``@attributes(name1, name2, ...)`` class decorator?
|
||||
|
||||
|
||||
Overloading ``isinstance()`` and ``issubclass()``
|
||||
-------------------------------------------------
|
||||
|
@ -213,7 +218,7 @@ 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.
|
||||
``C.__instancecheck__(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.
|
||||
|
@ -272,11 +277,12 @@ example, the ``Iterator`` class has an ``__iter__`` method returning
|
|||
itself, fulfilling an important invariant of iterators (which in
|
||||
Python 2 has to be implemented anew by each iterator class).
|
||||
|
||||
No ABCs override ``__init__``, ``__new__``, ``__str__`` or
|
||||
``__repr__``. Defining a standard constructor signature would
|
||||
unnecessarily constrain custom container types, for example Patricia
|
||||
trees or gdbm files. Defining a specific string representation for a
|
||||
collection is similarly left up to individual implementations.
|
||||
No ABCs defined in the PEP override ``__init__``, ``__new__``,
|
||||
``__str__`` or ``__repr__``. Defining a standard constructor
|
||||
signature would unnecessarily constrain custom container types, for
|
||||
example Patricia trees or gdbm files. Defining a specific string
|
||||
representation for a collection is similarly left up to individual
|
||||
implementations.
|
||||
|
||||
|
||||
Ordering ABCs
|
||||
|
@ -328,6 +334,8 @@ These abstract classes represent single methods like ``__iter__`` or
|
|||
**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
|
||||
not immutable; its ``__hash__`` method raises ``TypeError``.
|
||||
(This is because it recursively tries to compute the hash of each
|
||||
member; if a member is unhashable it raises ``TypeError``.)
|
||||
|
||||
``Iterable``
|
||||
The base class for classes defining ``__iter__``. The
|
||||
|
@ -357,18 +365,20 @@ These abstract classes represent single methods like ``__iter__`` or
|
|||
``Iterable``, then ``(x in o for x in o)`` should be a generator
|
||||
yielding only True values for any instance ``o`` of ``C``.
|
||||
|
||||
**Note:** strictly speaking, there are three variants of this method's
|
||||
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
|
||||
sequences, which is slow: O(N). The third one is for subsequence
|
||||
checking on (character or byte) strings, which is also slow: O(N).
|
||||
Would it make sense to distinguish these? The signature of the
|
||||
third variant is different, since it takes a sequence (typically
|
||||
of the same type as the method's target) intead of an element.
|
||||
For now, I'm using the same type for all three. This means that
|
||||
is is possible for ``x in o`` to be True even though ``x`` is
|
||||
never yielded by ``iter(o)``. A suggested name for the third form
|
||||
is ``Searchable``.
|
||||
**Open issues:** strictly speaking, there are three variants of
|
||||
this method's 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 sequences, which is slow: O(N). The third one is for
|
||||
subsequence checking on (character or byte) strings, which is also
|
||||
slow: O(N). Would it make sense to distinguish these? The
|
||||
signature of the third variant is different, since it takes a
|
||||
sequence (typically of the same type as the method's target)
|
||||
intead of an element. For now, I'm using the same type for all
|
||||
three. This means that is is possible for ``x in o`` to be True
|
||||
even though ``x`` is never yielded by ``iter(o)``. A suggested
|
||||
name for the third form is ``Searchable`` (though people have
|
||||
objected against this name on the grounds that it has the wrong
|
||||
association).
|
||||
|
||||
|
||||
Sets
|
||||
|
@ -489,9 +499,10 @@ out of the scope of a pragmatic proposal like this.
|
|||
implementation raises ``NotImplementedError``.
|
||||
|
||||
``.pop()``
|
||||
Concrete method that removes an arbitrary item. If the set is
|
||||
empty, it raises ``KeyError``. The default implementation
|
||||
removes the first item returned by the set's iterator.
|
||||
Concrete method that removes and returns an arbitrary item.
|
||||
If the set is empty, it raises ``KeyError``. The default
|
||||
implementation removes the first item returned by the set's
|
||||
iterator.
|
||||
|
||||
``.toggle(x)``
|
||||
Concrete method returning a ``bool`` that adds x to the set if
|
||||
|
@ -543,7 +554,7 @@ The built-in type ``dict`` derives from ``MutableMapping``.
|
|||
Concrete method returning ``self[key]`` if this does not raise
|
||||
``KeyError``, and the ``default`` value if it does.
|
||||
|
||||
``.__contains__()``
|
||||
``.__contains__(key)``
|
||||
Concrete method returning ``True`` if ``self[key]`` does not
|
||||
raise ``KeyError``, and ``False`` if it does.
|
||||
|
||||
|
@ -553,42 +564,44 @@ The built-in type ``dict`` derives from ``MutableMapping``.
|
|||
are also referred to as items. The items also form a set.
|
||||
Methods:
|
||||
|
||||
``__len__``
|
||||
``.__len__()``
|
||||
Abstract method returning the length of the key set.
|
||||
|
||||
``__iter__``
|
||||
``.__iter__()``
|
||||
Abstract method returning each key in the key set exactly once.
|
||||
|
||||
``__eq__``
|
||||
``.__eq__(obj)``
|
||||
Concrete method for comparing mappings. Two mappings, even
|
||||
with different implementations, can be compared for equality,
|
||||
and are considered equal if and only iff their item sets are
|
||||
and are considered equal if and only if their item sets are
|
||||
equal. **Open issues:** should we define comparison of
|
||||
instances of different concrete mapping types this way?
|
||||
|
||||
``keys``
|
||||
``.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``
|
||||
``.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``
|
||||
``.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``::
|
||||
The following invariants should hold for any mapping ``m``::
|
||||
|
||||
list(m.items()) == list(zip(m.keys(), m.values()))
|
||||
len(m.values()) == len(m.keys()) == len(m.items()) == len(m)
|
||||
[value for value in m.values()] == [m[key] for key in m.keys()]
|
||||
[item for item in m.items()] == [(key, m[key]) for key in m.keys()]
|
||||
|
||||
i.e. iterating over the items, keys and values should return
|
||||
results in the same order.
|
||||
|
|
Loading…
Reference in New Issue