[Python-checkins] r54946 - peps/trunk/pep-3119.txt

guido.van.rossum python-checkins at python.org
Wed Apr 25 02:17:29 CEST 2007


Author: guido.van.rossum
Date: Wed Apr 25 02:17:23 2007
New Revision: 54946

Modified:
   peps/trunk/pep-3119.txt
Log:
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.


Modified: peps/trunk/pep-3119.txt
==============================================================================
--- peps/trunk/pep-3119.txt	(original)
+++ peps/trunk/pep-3119.txt	Wed Apr 25 02:17:23 2007
@@ -16,9 +16,9 @@
 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 @@
 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 @@
 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.
+    class A:
+        @abstractmethod
+        def foo(self): pass
 
-* Even if we keep them separate, ``Abstract`` is quite unnecessary
-  since there is hardly any difference in complexity between this::
+    A()  # raises TypeError
 
-    class C(metaclass=AbstractClass):
-        @abstractmethod
-        def foo(self): ...
+    class B(A):
+        pass
 
-  and this::
+    B()  # raises TypeError
 
-    class C(Abstract):
-        @abstractmethod
-        def foo(self): ...
+    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 @@
     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 @@
 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 @@
 
 **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 @@
 
 **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 @@
 **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 @@
 * Keep abstract classes small, one per use case instead of one per
   concept.
 
-* What else?
-
 
 ABCs vs. Alternatives
 =====================
@@ -680,6 +672,15 @@
 .. [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


More information about the Python-checkins mailing list