Add pointer to implementation of @abstractmethod in C.

Change ABC framework description to only mention @abstractmethod
and unconditionally propose it as a built-in.
Some more editorializing; explain why we have BasicMapping.
This commit is contained in:
Guido van Rossum 2007-04-25 00:17:23 +00:00
parent f9b3dff1fb
commit 81cba80bfe
1 changed files with 69 additions and 68 deletions

View File

@ -16,9 +16,9 @@ Abstract
This is a proposal to add Abstract Base Class (ABC) support to Python
3000. It proposes:
* An "ABC support framework" which defines a metaclass, a base class,
a decorator, and some helpers that make it easy to define ABCs.
This will be added as a new library module named "abc".
* An "ABC support framework" which defines a built-in decorator that
can be used to define abstract methods. A class containing an
abstract method that isn't overridden cannot be instantiated.
* Specific ABCs for containers and iterators, to be added to the
collections module.
@ -119,10 +119,10 @@ ones are kept.
Specification
=============
The specification follows the four categories listed in the abstract:
The specification follows the categories listed in the abstract:
* An "ABC support framework" which defines a metaclass, a base class,
a decorator, and some helpers that make it easy to define ABCs.
* An "ABC support framework" which defines a built-in decorator that
make it easy to define ABCs, and mechanisms to support it.
* Specific ABCs for containers and iterators, to be added to the
collections module.
@ -131,58 +131,48 @@ The specification follows the four categories listed in the abstract:
ABC Support Framework
---------------------
We define the following four new built-in objects that help defining
ABCs:
We define a new built-in decorator, ``@abstractmethod``, to be used to
declare abstract methods. A class containing at least one method
declared with this decorator that hasn't been overridden yet cannot be
instantiated. Such a methods may be called from the overriding method
in the subclass (using ``super`` or direct invocation). For example::
``@abstractmethod``
A decorator used to declare abstract methods. This should only be
used with classes whose class is derived from ``Abstract`` below.
A class containing at least one method declared with this
decorator that hasn't been overridden yet cannot be instantiated.
Such a methods may be called from the overriding method in the
subclass (using ``super`` or direct invocation).
``AbstractClass``
A metaclass to be used with classes containing abstract methods.
Classes whose metaclass is (or derives from) ``AbstractClass``
cannot be instantiated unless all methods declared abstract using
the ``@abstractmethod`` decorator have been overridden by concrete
methods.
``Abstract``
An empty helper class whose metaclass is ``AbstractClass``. This
only exists as a minor convenience; deriving a class from
``Abstract`` is the same as setting its metaclass to
``AbstractClass``.
``AbstractInstantiationError``
The exception raised when attempting to instantiate an abstract
class. It derives from ``TypeError``.
**Open issues:**
* Implementing the prohibition on instantiation may weigh down
instance creation of popular built-in classes like ``tuple`` or
``str``. Perhaps concrete built-in classes can use a shortcut; or
perhaps there's a more efficient implementation.
* Do we even need ``Abstract`` and ``AbstractClass``? Their
functionality can be subsumed into ``object`` and ``type``,
respectively.
* Even if we keep them separate, ``Abstract`` is quite unnecessary
since there is hardly any difference in complexity between this::
class C(metaclass=AbstractClass):
class A:
@abstractmethod
def foo(self): ...
def foo(self): pass
and this::
A() # raises TypeError
class C(Abstract):
@abstractmethod
def foo(self): ...
class B(A):
pass
B() # raises TypeError
class C(A):
def foo(self): print(42)
C() # works
**Implementation:** The ``@abstractmethod`` decorator sets the
function attribute ``__isabstractmethod__`` to the value ``True``.
The ``type.__new__`` method computes the type attribute
``__abstractmethods__`` as the set of all method names that have an
``__isabstractmethod__`` attribute whose value is true. It does this
by combining the ``__abstractmethods__` attributes of the base
classes, adding the names of all methods in the new class dict that
have a true ``__isabstractmethod__`` attribute, and removing the names
of all methods in the new class dict that don't have a true
``__isabstractmethod__`` attribute. If the resulting
``__abstractmethods__`` set is non-empty, the class is considered
abstract, and attempts to instantiate it will raise ``TypeError``.
(CPython can uses an internal flag ``Py_TPFLAGS_ABSTRACT`` to speed up
this check [6]_.)
**Discussion:** Unlike C++ or Java, abstract methods as defined here
may have an implementation. This implementation can be called via the
``super`` mechanism from the class that overrides it. This could be
useful as an end-point for a super-call in framework using a
cooperative multiple-inheritance [7]_, [8]_.
ABCs for Containers and Iterators
@ -279,7 +269,7 @@ These abstract classes represent single methods like ``__iter__`` or
The abstract ``__len__`` method returns 0. **Invariant:** If a
class ``C`` derives from ``Sized`` as well as from ``Iterable``,
the invariant ``sum(1 for x in o) == len(o)`` should hold for any
instance ``o`` of ``C``. **Open issue:** Is ``Sized`` the best
instance ``o`` of ``C``. **Open issues:** Is ``Sized`` the best
name? Proposed alternatives already tentatively rejected:
``Finite`` (nobody understood it), ``Lengthy``, ``Sizeable`` (both
too cute), ``Countable`` (the set of natural numbers is a
@ -438,7 +428,16 @@ out of the scope of a pragmatic proposal like this.
Mappings
''''''''
These abstract classes represent various stages of mapping-ness.
These abstract classes represent various stages of mapping-ness. The
``Mapping`` class represents the most common read-only mapping API.
However, code *accepting* a mapping is encouraged to check for the
``BasicMapping`` ABC when iteration is not used. This allows for
certain "black-box" implementations that can look up values by key but
don't provide a convenient iteration API. A hypothetical example
would be an interface to a hierarchical filesystem, where keys are
pathnames relative to some root directory. Iterating over all
pathnames would presumably take forever, as would counting the number
of valid pathnames.
The built-in type ``dict`` derives from ``MutableMapping``.
@ -488,10 +487,6 @@ The built-in type ``dict`` derives from ``MutableMapping``.
**Open issues:**
* Do we need both ``BasicMapping`` and ``Mapping``? We could just
start with ``Mapping``; but I believe there's some use for a
non-iterable mapping that nevertheless behaves like a basic mapping.
* We should say more about mapping view types.
@ -545,8 +540,8 @@ deriving from ``MutableSequence``, and (Unicode) character strings
**Open issues:** define the base interfaces for these so alternative
implementations and subclasses know what they are in for. This may be
the subject of a new PEP or PEPs (maybe PEP 358 can be co-opted for
the ``bytes`` type).
the subject of a new PEP or PEPs (PEP 358 should be co-opted for the
``bytes`` type).
ABCs for Numbers
@ -555,16 +550,15 @@ ABCs for Numbers
**Open issues:** Define: ``Number``, ``Complex``, ``Real``,
``Rational``, ``Integer``. Maybe also ``Cardinal`` (``Integer`` >=
0)? We probably also need ``Index``, which converts to ``Integer``
using ``__index__``. This should probably be moved out to a separate
PEP.
using ``__index__``. This should be moved out to a separate PEP.
Guidelines for Writing ABCs
---------------------------
Some suggestions:
Some suggestions for writing ABCs:
* Use ``@abstractmethod`` and the ``Abstract`` base class.
* Use the ``@abstractmethod`` decorator.
* Define abstract methods that could be useful as an end point when
called via a super chain.
@ -575,8 +569,6 @@ Some suggestions:
* Keep abstract classes small, one per use case instead of one per
concept.
* What else?
ABCs vs. Alternatives
=====================
@ -680,6 +672,15 @@ References
.. [5] Charming Python: Scaling a new PEAK, by David Mertz
(http://www-128.ibm.com/developerworks/library/l-cppeak2/)
.. [6] Implementation of @abstractmethod
(http://python.org/sf/1706989)
.. [7] Unifying types and classes in Python 2.2, by GvR
(http://www.python.org/download/releases/2.2.3/descrintro/)
.. [8] "Putting Metaclasses to Work: A New Dimension in Object-Oriented
Programming", by Ira R. Forman and Scott H. Danforth
(http://www.amazon.com/gp/product/0201433052)
Copyright