python-peps/pep-3119/index.html

955 lines
92 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 3119 Introducing Abstract Base Classes | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-3119/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 3119 Introducing Abstract Base Classes | peps.python.org'>
<meta property="og:description" content="This is a proposal to add Abstract Base Class (ABC) support to Python 3000. It proposes:">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-3119/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This is a proposal to add Abstract Base Class (ABC) support to Python 3000. It proposes:">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 3119</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 3119 Introducing Abstract Base Classes</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Guido van Rossum &lt;guido&#32;&#97;t&#32;python.org&gt;, Talin &lt;viridia&#32;&#97;t&#32;gmail.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">18-Apr-2007</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">3.0</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">26-Apr-2007, 11-May-2007</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a><ul>
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
</ul>
</li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#overloading-isinstance-and-issubclass">Overloading <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> and <code class="docutils literal notranslate"><span class="pre">issubclass()</span></code></a></li>
<li><a class="reference internal" href="#the-abc-module-an-abc-support-framework">The <code class="docutils literal notranslate"><span class="pre">abc</span></code> Module: an ABC Support Framework</a></li>
<li><a class="reference internal" href="#abcs-for-containers-and-iterators">ABCs for Containers and Iterators</a><ul>
<li><a class="reference internal" href="#one-trick-ponies">One Trick Ponies</a></li>
<li><a class="reference internal" href="#sets">Sets</a></li>
<li><a class="reference internal" href="#mappings">Mappings</a></li>
<li><a class="reference internal" href="#sequences">Sequences</a></li>
</ul>
</li>
<li><a class="reference internal" href="#strings">Strings</a></li>
</ul>
</li>
<li><a class="reference internal" href="#abcs-vs-alternatives">ABCs vs. Alternatives</a><ul>
<li><a class="reference internal" href="#abcs-vs-duck-typing">ABCs vs. Duck Typing</a></li>
<li><a class="reference internal" href="#abcs-vs-generic-functions">ABCs vs. Generic Functions</a></li>
<li><a class="reference internal" href="#abcs-vs-interfaces">ABCs vs. Interfaces</a></li>
</ul>
</li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This is a proposal to add Abstract Base Class (ABC) support to Python
3000. It proposes:</p>
<ul class="simple">
<li>A way to overload <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> and <code class="docutils literal notranslate"><span class="pre">issubclass()</span></code>.</li>
<li>A new module <code class="docutils literal notranslate"><span class="pre">abc</span></code> which serves as an “ABC support framework”. It
defines a metaclass for use with ABCs and a decorator that can be
used to define abstract methods.</li>
<li>Specific ABCs for containers and iterators, to be added to the
collections module.</li>
</ul>
<p>Much of the thinking that went into the proposal is not about the
specific mechanism of ABCs, as contrasted with Interfaces or Generic
Functions (GFs), but about clarifying philosophical issues like “what
makes a set”, “what makes a mapping” and “what makes a sequence”.</p>
<p>Theres also a companion <a class="pep reference internal" href="../pep-3141/" title="PEP 3141 A Type Hierarchy for Numbers">PEP 3141</a>, which defines ABCs for numeric
types.</p>
<section id="acknowledgements">
<h3><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h3>
<p>Talin wrote the Rationale below <a class="footnote-reference brackets" href="#id13" id="id1">[1]</a> as well as most of the section on
ABCs vs. Interfaces. For that alone he deserves co-authorship. The
rest of the PEP uses “I” referring to the first author.</p>
</section>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>In the domain of object-oriented programming, the usage patterns for
interacting with an object can be divided into two basic categories,
which are invocation and inspection.</p>
<p>Invocation means interacting with an object by invoking its methods.
Usually this is combined with polymorphism, so that invoking a given
method may run different code depending on the type of an object.</p>
<p>Inspection means the ability for external code (outside of the
objects methods) to examine the type or properties of that object,
and make decisions on how to treat that object based on that
information.</p>
<p>Both usage patterns serve the same general end, which is to be able to
support the processing of diverse and potentially novel objects in a
uniform way, but at the same time allowing processing decisions to be
customized for each different type of object.</p>
<p>In classical OOP theory, invocation is the preferred usage pattern,
and inspection is actively discouraged, being considered a relic of an
earlier, procedural programming style. However, in practice this view
is simply too dogmatic and inflexible, and leads to a kind of design
rigidity that is very much at odds with the dynamic nature of a
language like Python.</p>
<p>In particular, there is often a need to process objects in a way that
wasnt anticipated by the creator of the object class. It is not
always the best solution to build in to every object methods that
satisfy the needs of every possible user of that object. Moreover,
there are many powerful dispatch philosophies that are in direct
contrast to the classic OOP requirement of behavior being strictly
encapsulated within an object, examples being rule or pattern-match
driven logic.</p>
<p>On the other hand, one of the criticisms of inspection by classic
OOP theorists is the lack of formalisms and the ad hoc nature of what
is being inspected. In a language such as Python, in which almost any
aspect of an object can be reflected and directly accessed by external
code, there are many different ways to test whether an object conforms
to a particular protocol or not. For example, if asking is this
object a mutable sequence container?, one can look for a base class
of list, or one can look for a method named __getitem__. But note
that although these tests may seem obvious, neither of them are
correct, as one generates false negatives, and the other false
positives.</p>
<p>The generally agreed-upon remedy is to standardize the tests, and
group them into a formal arrangement. This is most easily done by
associating with each class a set of standard testable properties,
either via the inheritance mechanism or some other means. Each test
carries with it a set of promises: it contains a promise about the
general behavior of the class, and a promise as to what other class
methods will be available.</p>
<p>This PEP proposes a particular strategy for organizing these tests
known as Abstract Base Classes, or ABC. ABCs are simply Python
classes that are added into an objects inheritance tree to signal
certain features of that object to an external inspector. Tests are
done using <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code>, and the presence of a particular ABC
means that the test has passed.</p>
<p>In addition, the ABCs define a minimal set of methods that establish
the characteristic behavior of the type. Code that discriminates
objects based on their ABC type can trust that those methods will
always be present. Each of these methods are accompanied by an
generalized abstract semantic definition that is described in the
documentation for the ABC. These standard semantic definitions are
not enforced, but are strongly recommended.</p>
<p>Like all other things in Python, these promises are in the nature of a
friendly agreement, which in this case means that while the
language does enforce some of the promises made in the ABC, it is up
to the implementer of the concrete class to insure that the remaining
ones are kept.</p>
</section>
<section id="specification">
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<p>The specification follows the categories listed in the abstract:</p>
<ul class="simple">
<li>A way to overload <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> and <code class="docutils literal notranslate"><span class="pre">issubclass()</span></code>.</li>
<li>A new module <code class="docutils literal notranslate"><span class="pre">abc</span></code> which serves as an “ABC support framework”. It
defines a metaclass for use with ABCs and a decorator that can be
used to define abstract methods.</li>
<li>Specific ABCs for containers and iterators, to be added to the
collections module.</li>
</ul>
<section id="overloading-isinstance-and-issubclass">
<h3><a class="toc-backref" href="#overloading-isinstance-and-issubclass" role="doc-backlink">Overloading <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> and <code class="docutils literal notranslate"><span class="pre">issubclass()</span></code></a></h3>
<p>During the development of this PEP and of its companion, <a class="pep reference internal" href="../pep-3141/" title="PEP 3141 A Type Hierarchy for Numbers">PEP 3141</a>, we
repeatedly faced the choice between standardizing more, fine-grained
ABCs or fewer, coarse-grained ones. For example, at one stage, PEP
3141 introduced the following stack of base classes used for complex
numbers: MonoidUnderPlus, AdditiveGroup, Ring, Field, Complex (each
derived from the previous). And the discussion mentioned several
other algebraic categorizations that were left out: Algebraic,
Transcendental, and IntegralDomain, and PrincipalIdealDomain. In
earlier versions of the current PEP, we considered the use cases for
separate classes like Set, ComposableSet, MutableSet, HashableSet,
MutableComposableSet, HashableComposableSet.</p>
<p>The dilemma here is that wed rather have fewer ABCs, but then what
should a user do who needs a less refined ABC? Consider e.g. the
plight of a mathematician who wants to define their own kind of
Transcendental numbers, but also wants float and int to be considered
Transcendental. <a class="pep reference internal" href="../pep-3141/" title="PEP 3141 A Type Hierarchy for Numbers">PEP 3141</a> originally proposed to patch float.__bases__
for that purpose, but there are some good reasons to keep the built-in
types immutable (for one, they are shared between all Python
interpreters running in the same address space, as is used by
mod_python <a class="footnote-reference brackets" href="#id24" id="id2">[16]</a>).</p>
<p>Another example would be someone who wants to define a generic
function (<a class="pep reference internal" href="../pep-3124/" title="PEP 3124 Overloading, Generic Functions, Interfaces, and Adaptation">PEP 3124</a>) for any sequence that has an <code class="docutils literal notranslate"><span class="pre">append()</span></code> method.
The <code class="docutils literal notranslate"><span class="pre">Sequence</span></code> ABC (see below) doesnt promise the <code class="docutils literal notranslate"><span class="pre">append()</span></code>
method, while <code class="docutils literal notranslate"><span class="pre">MutableSequence</span></code> requires not only <code class="docutils literal notranslate"><span class="pre">append()</span></code> but
also various other mutating methods.</p>
<p>To solve these and similar dilemmas, the next section will propose a
metaclass for use with ABCs that will allow us to add an ABC as a
“virtual base class” (not the same concept as in C++) to any class,
including to another ABC. This allows the standard library to define
ABCs <code class="docutils literal notranslate"><span class="pre">Sequence</span></code> and <code class="docutils literal notranslate"><span class="pre">MutableSequence</span></code> and register these as
virtual base classes for built-in types like <code class="docutils literal notranslate"><span class="pre">basestring</span></code>, <code class="docutils literal notranslate"><span class="pre">tuple</span></code>
and <code class="docutils literal notranslate"><span class="pre">list</span></code>, so that for example the following conditions are all
true:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">isinstance</span><span class="p">([],</span> <span class="n">Sequence</span><span class="p">)</span>
<span class="nb">issubclass</span><span class="p">(</span><span class="nb">list</span><span class="p">,</span> <span class="n">Sequence</span><span class="p">)</span>
<span class="nb">issubclass</span><span class="p">(</span><span class="nb">list</span><span class="p">,</span> <span class="n">MutableSequence</span><span class="p">)</span>
<span class="nb">isinstance</span><span class="p">((),</span> <span class="n">Sequence</span><span class="p">)</span>
<span class="ow">not</span> <span class="nb">issubclass</span><span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="n">MutableSequence</span><span class="p">)</span>
<span class="nb">isinstance</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="n">Sequence</span><span class="p">)</span>
<span class="nb">issubclass</span><span class="p">(</span><span class="nb">bytearray</span><span class="p">,</span> <span class="n">MutableSequence</span><span class="p">)</span>
</pre></div>
</div>
<p>The primary mechanism proposed here is to allow overloading the
built-in functions <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> and <code class="docutils literal notranslate"><span class="pre">issubclass()</span></code>. The
overloading works as follows: The call <code class="docutils literal notranslate"><span class="pre">isinstance(x,</span> <span class="pre">C)</span></code> first
checks whether <code class="docutils literal notranslate"><span class="pre">C.__instancecheck__</span></code> exists, and if so, calls
<code class="docutils literal notranslate"><span class="pre">C.__instancecheck__(x)</span></code> instead of its normal implementation.
Similarly, the call <code class="docutils literal notranslate"><span class="pre">issubclass(D,</span> <span class="pre">C)</span></code> first checks whether
<code class="docutils literal notranslate"><span class="pre">C.__subclasscheck__</span></code> exists, and if so, calls
<code class="docutils literal notranslate"><span class="pre">C.__subclasscheck__(D)</span></code> instead of its normal implementation.</p>
<p>Note that the magic names are not <code class="docutils literal notranslate"><span class="pre">__isinstance__</span></code> and
<code class="docutils literal notranslate"><span class="pre">__issubclass__</span></code>; this is because the reversal of the arguments
could cause confusion, especially for the <code class="docutils literal notranslate"><span class="pre">issubclass()</span></code> overloader.</p>
<p>A prototype implementation of this is given in <a class="footnote-reference brackets" href="#id20" id="id3">[12]</a>.</p>
<p>Here is an example with (naively simple) implementations of
<code class="docutils literal notranslate"><span class="pre">__instancecheck__</span></code> and <code class="docutils literal notranslate"><span class="pre">__subclasscheck__</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">ABCMeta</span><span class="p">(</span><span class="nb">type</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__instancecheck__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">inst</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Implement isinstance(inst, cls).&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="nb">any</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="fm">__subclasscheck__</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
<span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="p">{</span><span class="nb">type</span><span class="p">(</span><span class="n">inst</span><span class="p">),</span> <span class="n">inst</span><span class="o">.</span><span class="vm">__class__</span><span class="p">})</span>
<span class="k">def</span> <span class="fm">__subclasscheck__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">sub</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Implement issubclass(sub, cls).&quot;&quot;&quot;</span>
<span class="n">candidates</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;__subclass__&quot;</span><span class="p">,</span> <span class="nb">set</span><span class="p">())</span> <span class="o">|</span> <span class="p">{</span><span class="bp">cls</span><span class="p">}</span>
<span class="k">return</span> <span class="nb">any</span><span class="p">(</span><span class="n">c</span> <span class="ow">in</span> <span class="n">candidates</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">sub</span><span class="o">.</span><span class="n">mro</span><span class="p">())</span>
<span class="k">class</span> <span class="nc">Sequence</span><span class="p">(</span><span class="n">metaclass</span><span class="o">=</span><span class="n">ABCMeta</span><span class="p">):</span>
<span class="n">__subclass__</span> <span class="o">=</span> <span class="p">{</span><span class="nb">list</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">}</span>
<span class="k">assert</span> <span class="nb">issubclass</span><span class="p">(</span><span class="nb">list</span><span class="p">,</span> <span class="n">Sequence</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">issubclass</span><span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="n">Sequence</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">AppendableSequence</span><span class="p">(</span><span class="n">Sequence</span><span class="p">):</span>
<span class="n">__subclass__</span> <span class="o">=</span> <span class="p">{</span><span class="nb">list</span><span class="p">}</span>
<span class="k">assert</span> <span class="nb">issubclass</span><span class="p">(</span><span class="nb">list</span><span class="p">,</span> <span class="n">AppendableSequence</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">([],</span> <span class="n">AppendableSequence</span><span class="p">)</span>
<span class="k">assert</span> <span class="ow">not</span> <span class="nb">issubclass</span><span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="n">AppendableSequence</span><span class="p">)</span>
<span class="k">assert</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">((),</span> <span class="n">AppendableSequence</span><span class="p">)</span>
</pre></div>
</div>
<p>The next section proposes a full-fledged implementation.</p>
</section>
<section id="the-abc-module-an-abc-support-framework">
<h3><a class="toc-backref" href="#the-abc-module-an-abc-support-framework" role="doc-backlink">The <code class="docutils literal notranslate"><span class="pre">abc</span></code> Module: an ABC Support Framework</a></h3>
<p>The new standard library module <code class="docutils literal notranslate"><span class="pre">abc</span></code>, written in pure Python,
serves as an ABC support framework. It defines a metaclass
<code class="docutils literal notranslate"><span class="pre">ABCMeta</span></code> and decorators <code class="docutils literal notranslate"><span class="pre">&#64;abstractmethod</span></code> and
<code class="docutils literal notranslate"><span class="pre">&#64;abstractproperty</span></code>. A sample implementation is given by <a class="footnote-reference brackets" href="#id21" id="id4">[13]</a>.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">ABCMeta</span></code> class overrides <code class="docutils literal notranslate"><span class="pre">__instancecheck__</span></code> and
<code class="docutils literal notranslate"><span class="pre">__subclasscheck__</span></code> and defines a <code class="docutils literal notranslate"><span class="pre">register</span></code> method. The
<code class="docutils literal notranslate"><span class="pre">register</span></code> method takes one argument, which must be a class; after
the call <code class="docutils literal notranslate"><span class="pre">B.register(C)</span></code>, the call <code class="docutils literal notranslate"><span class="pre">issubclass(C,</span> <span class="pre">B)</span></code> will return
True, by virtue of <code class="docutils literal notranslate"><span class="pre">B.__subclasscheck__(C)</span></code> returning True.
Also, <code class="docutils literal notranslate"><span class="pre">isinstance(x,</span> <span class="pre">B)</span></code> is equivalent to <code class="docutils literal notranslate"><span class="pre">issubclass(x.__class__,</span>
<span class="pre">B)</span> <span class="pre">or</span> <span class="pre">issubclass(type(x),</span> <span class="pre">B)</span></code>. (It is possible <code class="docutils literal notranslate"><span class="pre">type(x)</span></code> and
<code class="docutils literal notranslate"><span class="pre">x.__class__</span></code> are not the same object, e.g. when x is a proxy
object.)</p>
<p>These methods are intended to be called on classes whose metaclass
is (derived from) <code class="docutils literal notranslate"><span class="pre">ABCMeta</span></code>; for example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">abc</span> <span class="kn">import</span> <span class="n">ABCMeta</span>
<span class="k">class</span> <span class="nc">MyABC</span><span class="p">(</span><span class="n">metaclass</span><span class="o">=</span><span class="n">ABCMeta</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">MyABC</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="nb">tuple</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">issubclass</span><span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="n">MyABC</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">((),</span> <span class="n">MyABC</span><span class="p">)</span>
</pre></div>
</div>
<p>The last two asserts are equivalent to the following two:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">assert</span> <span class="n">MyABC</span><span class="o">.</span><span class="fm">__subclasscheck__</span><span class="p">(</span><span class="nb">tuple</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">MyABC</span><span class="o">.</span><span class="fm">__instancecheck__</span><span class="p">(())</span>
</pre></div>
</div>
<p>Of course, you can also directly subclass MyABC:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="n">MyABC</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">assert</span> <span class="nb">issubclass</span><span class="p">(</span><span class="n">MyClass</span><span class="p">,</span> <span class="n">MyABC</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">MyClass</span><span class="p">(),</span> <span class="n">MyABC</span><span class="p">)</span>
</pre></div>
</div>
<p>Also, of course, a tuple is not a <code class="docutils literal notranslate"><span class="pre">MyClass</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">assert</span> <span class="ow">not</span> <span class="nb">issubclass</span><span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="n">MyClass</span><span class="p">)</span>
<span class="k">assert</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">((),</span> <span class="n">MyClass</span><span class="p">)</span>
</pre></div>
</div>
<p>You can register another class as a subclass of <code class="docutils literal notranslate"><span class="pre">MyClass</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">MyClass</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="nb">list</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">issubclass</span><span class="p">(</span><span class="nb">list</span><span class="p">,</span> <span class="n">MyClass</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">issubclass</span><span class="p">(</span><span class="nb">list</span><span class="p">,</span> <span class="n">MyABC</span><span class="p">)</span>
</pre></div>
</div>
<p>You can also register another ABC:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">AnotherClass</span><span class="p">(</span><span class="n">metaclass</span><span class="o">=</span><span class="n">ABCMeta</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">AnotherClass</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">basestring</span><span class="p">)</span>
<span class="n">MyClass</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">AnotherClass</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">MyABC</span><span class="p">)</span>
</pre></div>
</div>
<p>That last assert requires tracing the following superclass-subclass
relationships:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">MyABC</span> <span class="o">-&gt;</span> <span class="n">MyClass</span> <span class="p">(</span><span class="n">using</span> <span class="n">regular</span> <span class="n">subclassing</span><span class="p">)</span>
<span class="n">MyClass</span> <span class="o">-&gt;</span> <span class="n">AnotherClass</span> <span class="p">(</span><span class="n">using</span> <span class="n">registration</span><span class="p">)</span>
<span class="n">AnotherClass</span> <span class="o">-&gt;</span> <span class="n">basestring</span> <span class="p">(</span><span class="n">using</span> <span class="n">registration</span><span class="p">)</span>
<span class="n">basestring</span> <span class="o">-&gt;</span> <span class="nb">str</span> <span class="p">(</span><span class="n">using</span> <span class="n">regular</span> <span class="n">subclassing</span><span class="p">)</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">abc</span></code> module also defines a new decorator, <code class="docutils literal notranslate"><span class="pre">&#64;abstractmethod</span></code>,
to be used to declare abstract methods. A class containing at least
one method declared with this decorator that hasnt been overridden
yet cannot be instantiated. Such methods may be called from the
overriding method in the subclass (using <code class="docutils literal notranslate"><span class="pre">super</span></code> or direct
invocation). For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">abc</span> <span class="kn">import</span> <span class="n">ABCMeta</span><span class="p">,</span> <span class="n">abstractmethod</span>
<span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="n">metaclass</span><span class="o">=</span><span class="n">ABCMeta</span><span class="p">):</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">pass</span>
<span class="n">A</span><span class="p">()</span> <span class="c1"># raises TypeError</span>
<span class="k">class</span> <span class="nc">B</span><span class="p">(</span><span class="n">A</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">B</span><span class="p">()</span> <span class="c1"># raises TypeError</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">(</span><span class="n">A</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="nb">print</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span>
<span class="n">C</span><span class="p">()</span> <span class="c1"># works</span>
</pre></div>
</div>
<p><strong>Note:</strong> The <code class="docutils literal notranslate"><span class="pre">&#64;abstractmethod</span></code> decorator should only be used
inside a class body, and only for classes whose metaclass is (derived
from) <code class="docutils literal notranslate"><span class="pre">ABCMeta</span></code>. Dynamically adding abstract methods to a class, or
attempting to modify the abstraction status of a method or class once
it is created, are not supported. The <code class="docutils literal notranslate"><span class="pre">&#64;abstractmethod</span></code> only
affects subclasses derived using regular inheritance; “virtual
subclasses” registered with the <code class="docutils literal notranslate"><span class="pre">register()</span></code> method are not affected.</p>
<p><strong>Implementation:</strong> The <code class="docutils literal notranslate"><span class="pre">&#64;abstractmethod</span></code> decorator sets the
function attribute <code class="docutils literal notranslate"><span class="pre">__isabstractmethod__</span></code> to the value <code class="docutils literal notranslate"><span class="pre">True</span></code>.
The <code class="docutils literal notranslate"><span class="pre">ABCMeta.__new__</span></code> method computes the type attribute
<code class="docutils literal notranslate"><span class="pre">__abstractmethods__</span></code> as the set of all method names that have an
<code class="docutils literal notranslate"><span class="pre">__isabstractmethod__</span></code> attribute whose value is true. It does this
by combining the <code class="docutils literal notranslate"><span class="pre">__abstractmethods__</span></code> attributes of the base
classes, adding the names of all methods in the new class dict that
have a true <code class="docutils literal notranslate"><span class="pre">__isabstractmethod__</span></code> attribute, and removing the names
of all methods in the new class dict that dont have a true
<code class="docutils literal notranslate"><span class="pre">__isabstractmethod__</span></code> attribute. If the resulting
<code class="docutils literal notranslate"><span class="pre">__abstractmethods__</span></code> set is non-empty, the class is considered
abstract, and attempts to instantiate it will raise <code class="docutils literal notranslate"><span class="pre">TypeError</span></code>.
(If this were implemented in CPython, an internal flag
<code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_ABSTRACT</span></code> could be used to speed up this check <a class="footnote-reference brackets" href="#id16" id="id5">[6]</a>.)</p>
<p><strong>Discussion:</strong> Unlike Javas abstract methods or C++s pure abstract
methods, abstract methods as defined here may have an implementation.
This implementation can be called via the <code class="docutils literal notranslate"><span class="pre">super</span></code> mechanism from the
class that overrides it. This could be useful as an end-point for a
super-call in framework using cooperative multiple-inheritance <a class="footnote-reference brackets" href="#id17" id="id6">[7]</a>,
<a class="footnote-reference brackets" href="#id18" id="id7">[8]</a>.</p>
<p>A second decorator, <code class="docutils literal notranslate"><span class="pre">&#64;abstractproperty</span></code>, is defined in order to
define abstract data attributes. Its implementation is a subclass of
the built-in <code class="docutils literal notranslate"><span class="pre">property</span></code> class that adds an <code class="docutils literal notranslate"><span class="pre">__isabstractmethod__</span></code>
attribute:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">abstractproperty</span><span class="p">(</span><span class="nb">property</span><span class="p">):</span>
<span class="n">__isabstractmethod__</span> <span class="o">=</span> <span class="kc">True</span>
</pre></div>
</div>
<p>It can be used in two ways:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">(</span><span class="n">metaclass</span><span class="o">=</span><span class="n">ABCMeta</span><span class="p">):</span>
<span class="c1"># A read-only property:</span>
<span class="nd">@abstractproperty</span>
<span class="k">def</span> <span class="nf">readonly</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__x</span>
<span class="c1"># A read-write property (cannot use decorator syntax):</span>
<span class="k">def</span> <span class="nf">getx</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__x</span>
<span class="k">def</span> <span class="nf">setx</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__x</span> <span class="o">=</span> <span class="n">value</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">abstractproperty</span><span class="p">(</span><span class="n">getx</span><span class="p">,</span> <span class="n">setx</span><span class="p">)</span>
</pre></div>
</div>
<p>Similar to abstract methods, a subclass inheriting an abstract
property (declared using either the decorator syntax or the longer
form) cannot be instantiated unless it overrides that abstract
property with a concrete property.</p>
</section>
<section id="abcs-for-containers-and-iterators">
<h3><a class="toc-backref" href="#abcs-for-containers-and-iterators" role="doc-backlink">ABCs for Containers and Iterators</a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">collections</span></code> module will define ABCs necessary and sufficient
to work with sets, mappings, sequences, and some helper types such as
iterators and dictionary views. All ABCs have the above-mentioned
<code class="docutils literal notranslate"><span class="pre">ABCMeta</span></code> as their metaclass.</p>
<p>The ABCs provide implementations of their abstract methods that are
technically valid but fairly useless; e.g. <code class="docutils literal notranslate"><span class="pre">__hash__</span></code> returns 0, and
<code class="docutils literal notranslate"><span class="pre">__iter__</span></code> returns an empty iterator. In general, the abstract
methods represent the behavior of an empty container of the indicated
type.</p>
<p>Some ABCs also provide concrete (i.e. non-abstract) methods; for
example, the <code class="docutils literal notranslate"><span class="pre">Iterator</span></code> class has an <code class="docutils literal notranslate"><span class="pre">__iter__</span></code> method returning
itself, fulfilling an important invariant of iterators (which in
Python 2 has to be implemented anew by each iterator class). These
ABCs can be considered “mix-in” classes.</p>
<p>No ABCs defined in the PEP override <code class="docutils literal notranslate"><span class="pre">__init__</span></code>, <code class="docutils literal notranslate"><span class="pre">__new__</span></code>,
<code class="docutils literal notranslate"><span class="pre">__str__</span></code> or <code class="docutils literal notranslate"><span class="pre">__repr__</span></code>. 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.</p>
<p><strong>Note:</strong> There are no ABCs for ordering operations (<code class="docutils literal notranslate"><span class="pre">__lt__</span></code>,
<code class="docutils literal notranslate"><span class="pre">__le__</span></code>, <code class="docutils literal notranslate"><span class="pre">__ge__</span></code>, <code class="docutils literal notranslate"><span class="pre">__gt__</span></code>). Defining these in a base class
(abstract or not) runs into problems with the accepted type for the
second operand. For example, if class <code class="docutils literal notranslate"><span class="pre">Ordering</span></code> defined
<code class="docutils literal notranslate"><span class="pre">__lt__</span></code>, one would assume that for any <code class="docutils literal notranslate"><span class="pre">Ordering</span></code> instances <code class="docutils literal notranslate"><span class="pre">x</span></code>
and <code class="docutils literal notranslate"><span class="pre">y</span></code>, <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">&lt;</span> <span class="pre">y</span></code> would be defined (even if it just defines a
partial ordering). But this cannot be the case: If both <code class="docutils literal notranslate"><span class="pre">list</span></code> and
<code class="docutils literal notranslate"><span class="pre">str</span></code> derived from <code class="docutils literal notranslate"><span class="pre">Ordering</span></code>, this would imply that <code class="docutils literal notranslate"><span class="pre">[1,</span> <span class="pre">2]</span> <span class="pre">&lt;</span>
<span class="pre">(1,</span> <span class="pre">2)</span></code> should be defined (and presumably return False), while in
fact (in Python 3000!) such “mixed-mode comparisons” operations are
explicitly forbidden and raise <code class="docutils literal notranslate"><span class="pre">TypeError</span></code>. See <a class="pep reference internal" href="../pep-3100/" title="PEP 3100 Miscellaneous Python 3.0 Plans">PEP 3100</a> and <a class="footnote-reference brackets" href="#id22" id="id8">[14]</a>
for more information. (This is a special case of a more general issue
with operations that take another argument of the same type).</p>
<section id="one-trick-ponies">
<h4><a class="toc-backref" href="#one-trick-ponies" role="doc-backlink">One Trick Ponies</a></h4>
<p>These abstract classes represent single methods like <code class="docutils literal notranslate"><span class="pre">__iter__</span></code> or
<code class="docutils literal notranslate"><span class="pre">__len__</span></code>.</p>
<dl>
<dt><code class="docutils literal notranslate"><span class="pre">Hashable</span></code></dt><dd>The base class for classes defining <code class="docutils literal notranslate"><span class="pre">__hash__</span></code>. The
<code class="docutils literal notranslate"><span class="pre">__hash__</span></code> method should return an integer. The abstract
<code class="docutils literal notranslate"><span class="pre">__hash__</span></code> method always returns 0, which is a valid (albeit
inefficient) implementation. <strong>Invariant:</strong> If classes <code class="docutils literal notranslate"><span class="pre">C1</span></code> and
<code class="docutils literal notranslate"><span class="pre">C2</span></code> both derive from <code class="docutils literal notranslate"><span class="pre">Hashable</span></code>, the condition <code class="docutils literal notranslate"><span class="pre">o1</span> <span class="pre">==</span> <span class="pre">o2</span></code>
must imply <code class="docutils literal notranslate"><span class="pre">hash(o1)</span> <span class="pre">==</span> <span class="pre">hash(o2)</span></code> for all instances <code class="docutils literal notranslate"><span class="pre">o1</span></code> of
<code class="docutils literal notranslate"><span class="pre">C1</span></code> and all instances <code class="docutils literal notranslate"><span class="pre">o2</span></code> of <code class="docutils literal notranslate"><span class="pre">C2</span></code>. In other words, two
objects should never compare equal if they have different hash
values.<p>Another constraint is that hashable objects, once created, should
never change their value (as compared by <code class="docutils literal notranslate"><span class="pre">==</span></code>) or their hash
value. If a class cannot guarantee this, it should not derive
from <code class="docutils literal notranslate"><span class="pre">Hashable</span></code>; if it cannot guarantee this for certain
instances, <code class="docutils literal notranslate"><span class="pre">__hash__</span></code> for those instances should raise a
<code class="docutils literal notranslate"><span class="pre">TypeError</span></code> exception.</p>
<p><strong>Note:</strong> 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 <code class="docutils literal notranslate"><span class="pre">__hash__</span></code> method raises <code class="docutils literal notranslate"><span class="pre">TypeError</span></code>.
(This is because it recursively tries to compute the hash of each
member; if a member is unhashable it raises <code class="docutils literal notranslate"><span class="pre">TypeError</span></code>.)</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">Iterable</span></code></dt><dd>The base class for classes defining <code class="docutils literal notranslate"><span class="pre">__iter__</span></code>. The
<code class="docutils literal notranslate"><span class="pre">__iter__</span></code> method should always return an instance of
<code class="docutils literal notranslate"><span class="pre">Iterator</span></code> (see below). The abstract <code class="docutils literal notranslate"><span class="pre">__iter__</span></code> method
returns an empty iterator.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">Iterator</span></code></dt><dd>The base class for classes defining <code class="docutils literal notranslate"><span class="pre">__next__</span></code>. This derives
from <code class="docutils literal notranslate"><span class="pre">Iterable</span></code>. The abstract <code class="docutils literal notranslate"><span class="pre">__next__</span></code> method raises
<code class="docutils literal notranslate"><span class="pre">StopIteration</span></code>. The concrete <code class="docutils literal notranslate"><span class="pre">__iter__</span></code> method returns
<code class="docutils literal notranslate"><span class="pre">self</span></code>. Note the distinction between <code class="docutils literal notranslate"><span class="pre">Iterable</span></code> and
<code class="docutils literal notranslate"><span class="pre">Iterator</span></code>: an <code class="docutils literal notranslate"><span class="pre">Iterable</span></code> can be iterated over, i.e. supports
the <code class="docutils literal notranslate"><span class="pre">__iter__</span></code> methods; an <code class="docutils literal notranslate"><span class="pre">Iterator</span></code> is what the built-in
function <code class="docutils literal notranslate"><span class="pre">iter()</span></code> returns, i.e. supports the <code class="docutils literal notranslate"><span class="pre">__next__</span></code>
method.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">Sized</span></code></dt><dd>The base class for classes defining <code class="docutils literal notranslate"><span class="pre">__len__</span></code>. The <code class="docutils literal notranslate"><span class="pre">__len__</span></code>
method should return an <code class="docutils literal notranslate"><span class="pre">Integer</span></code> (see “Numbers” below) &gt;= 0.
The abstract <code class="docutils literal notranslate"><span class="pre">__len__</span></code> method returns 0. <strong>Invariant:</strong> If a
class <code class="docutils literal notranslate"><span class="pre">C</span></code> derives from <code class="docutils literal notranslate"><span class="pre">Sized</span></code> as well as from <code class="docutils literal notranslate"><span class="pre">Iterable</span></code>,
the invariant <code class="docutils literal notranslate"><span class="pre">sum(1</span> <span class="pre">for</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">c)</span> <span class="pre">==</span> <span class="pre">len(c)</span></code> should hold for any
instance <code class="docutils literal notranslate"><span class="pre">c</span></code> of <code class="docutils literal notranslate"><span class="pre">C</span></code>.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">Container</span></code></dt><dd>The base class for classes defining <code class="docutils literal notranslate"><span class="pre">__contains__</span></code>. The
<code class="docutils literal notranslate"><span class="pre">__contains__</span></code> method should return a <code class="docutils literal notranslate"><span class="pre">bool</span></code>. The abstract
<code class="docutils literal notranslate"><span class="pre">__contains__</span></code> method returns <code class="docutils literal notranslate"><span class="pre">False</span></code>. <strong>Invariant:</strong> If a
class <code class="docutils literal notranslate"><span class="pre">C</span></code> derives from <code class="docutils literal notranslate"><span class="pre">Container</span></code> as well as from
<code class="docutils literal notranslate"><span class="pre">Iterable</span></code>, then <code class="docutils literal notranslate"><span class="pre">(x</span> <span class="pre">in</span> <span class="pre">c</span> <span class="pre">for</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">c)</span></code> should be a generator
yielding only True values for any instance <code class="docutils literal notranslate"><span class="pre">c</span></code> of <code class="docutils literal notranslate"><span class="pre">C</span></code>.</dd>
</dl>
<p><strong>Open issues:</strong> Conceivably, instead of using the ABCMeta metaclass,
these classes could override <code class="docutils literal notranslate"><span class="pre">__instancecheck__</span></code> and
<code class="docutils literal notranslate"><span class="pre">__subclasscheck__</span></code> to check for the presence of the applicable
special method; for example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Sized</span><span class="p">(</span><span class="n">metaclass</span><span class="o">=</span><span class="n">ABCMeta</span><span class="p">):</span>
<span class="nd">@abstractmethod</span>
<span class="k">def</span> <span class="fm">__hash__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="mi">0</span>
<span class="nd">@classmethod</span>
<span class="k">def</span> <span class="fm">__instancecheck__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="s2">&quot;__len__&quot;</span><span class="p">)</span>
<span class="nd">@classmethod</span>
<span class="k">def</span> <span class="fm">__subclasscheck__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">C</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="s2">&quot;__bases__&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="s2">&quot;__len__&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>This has the advantage of not requiring explicit registration.
However, the semantics are hard to get exactly right given the confusing
semantics of instance attributes vs. class attributes, and that a
class is an instance of its metaclass; the check for <code class="docutils literal notranslate"><span class="pre">__bases__</span></code> is
only an approximation of the desired semantics. <strong>Strawman:</strong> Lets
do it, but lets arrange it in such a way that the registration API
also works.</p>
</section>
<section id="sets">
<h4><a class="toc-backref" href="#sets" role="doc-backlink">Sets</a></h4>
<p>These abstract classes represent read-only sets and mutable sets. The
most fundamental set operation is the membership test, written as <code class="docutils literal notranslate"><span class="pre">x</span>
<span class="pre">in</span> <span class="pre">s</span></code> and implemented by <code class="docutils literal notranslate"><span class="pre">s.__contains__(x)</span></code>. This operation is
already defined by the <code class="docutils literal notranslate"><span class="pre">Container</span></code> class defined above. Therefore,
we define a set as a sized, iterable container for which certain
invariants from mathematical set theory hold.</p>
<p>The built-in type <code class="docutils literal notranslate"><span class="pre">set</span></code> derives from <code class="docutils literal notranslate"><span class="pre">MutableSet</span></code>. The built-in
type <code class="docutils literal notranslate"><span class="pre">frozenset</span></code> derives from <code class="docutils literal notranslate"><span class="pre">Set</span></code> and <code class="docutils literal notranslate"><span class="pre">Hashable</span></code>.</p>
<dl>
<dt><code class="docutils literal notranslate"><span class="pre">Set</span></code></dt><dd>This is a sized, iterable container, i.e., a subclass of
<code class="docutils literal notranslate"><span class="pre">Sized</span></code>, <code class="docutils literal notranslate"><span class="pre">Iterable</span></code> and <code class="docutils literal notranslate"><span class="pre">Container</span></code>. Not every subclass of
those three classes is a set though! Sets have the additional
invariant that each element occurs only once (as can be determined
by iteration), and in addition sets define concrete operators that
implement the inequality operations as subset/superset tests.
In general, the invariants for finite sets in mathematics
hold. <a class="footnote-reference brackets" href="#id19" id="id9">[11]</a><p>Sets with different implementations can be compared safely,
(usually) efficiently and correctly using the mathematical
definitions of the subset/supeset operations for finite sets.
The ordering operations have concrete implementations; subclasses
may override these for speed but should maintain the semantics.
Because <code class="docutils literal notranslate"><span class="pre">Set</span></code> derives from <code class="docutils literal notranslate"><span class="pre">Sized</span></code>, <code class="docutils literal notranslate"><span class="pre">__eq__</span></code> may take a
shortcut and return <code class="docutils literal notranslate"><span class="pre">False</span></code> immediately if two sets of unequal
length are compared. Similarly, <code class="docutils literal notranslate"><span class="pre">__le__</span></code> may return <code class="docutils literal notranslate"><span class="pre">False</span></code>
immediately if the first set has more members than the second set.
Note that set inclusion implements only a partial ordering;
e.g. <code class="docutils literal notranslate"><span class="pre">{1,</span> <span class="pre">2}</span></code> and <code class="docutils literal notranslate"><span class="pre">{1,</span> <span class="pre">3}</span></code> are not ordered (all three of
<code class="docutils literal notranslate"><span class="pre">&lt;</span></code>, <code class="docutils literal notranslate"><span class="pre">==</span></code> and <code class="docutils literal notranslate"><span class="pre">&gt;</span></code> return <code class="docutils literal notranslate"><span class="pre">False</span></code> for these arguments).
Sets cannot be ordered relative to mappings or sequences, but they
can be compared to those for equality (and then they always
compare unequal).</p>
<p>This class also defines concrete operators to compute union,
intersection, symmetric and asymmetric difference, respectively
<code class="docutils literal notranslate"><span class="pre">__or__</span></code>, <code class="docutils literal notranslate"><span class="pre">__and__</span></code>, <code class="docutils literal notranslate"><span class="pre">__xor__</span></code> and <code class="docutils literal notranslate"><span class="pre">__sub__</span></code>. These
operators should return instances of <code class="docutils literal notranslate"><span class="pre">Set</span></code>. The default
implementations call the overridable class method
<code class="docutils literal notranslate"><span class="pre">_from_iterable()</span></code> with an iterable argument. This factory
methods default implementation returns a <code class="docutils literal notranslate"><span class="pre">frozenset</span></code> instance;
it may be overridden to return another appropriate <code class="docutils literal notranslate"><span class="pre">Set</span></code>
subclass.</p>
<p>Finally, this class defines a concrete method <code class="docutils literal notranslate"><span class="pre">_hash</span></code> which
computes the hash value from the elements. Hashable subclasses of
<code class="docutils literal notranslate"><span class="pre">Set</span></code> can implement <code class="docutils literal notranslate"><span class="pre">__hash__</span></code> by calling <code class="docutils literal notranslate"><span class="pre">_hash</span></code> or they
can reimplement the same algorithm more efficiently; but the
algorithm implemented should be the same. Currently the algorithm
is fully specified only by the source code <a class="footnote-reference brackets" href="#id23" id="id10">[15]</a>.</p>
<p><strong>Note:</strong> the <code class="docutils literal notranslate"><span class="pre">issubset</span></code> and <code class="docutils literal notranslate"><span class="pre">issuperset</span></code> methods found on the
set type in Python 2 are not supported, as these are mostly just
aliases for <code class="docutils literal notranslate"><span class="pre">__le__</span></code> and <code class="docutils literal notranslate"><span class="pre">__ge__</span></code>.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">MutableSet</span></code></dt><dd>This is a subclass of <code class="docutils literal notranslate"><span class="pre">Set</span></code> implementing additional operations
to add and remove elements. The supported methods have the
semantics known from the <code class="docutils literal notranslate"><span class="pre">set</span></code> type in Python 2 (except for
<code class="docutils literal notranslate"><span class="pre">discard</span></code>, which is modeled after Java):<dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">.add(x)</span></code></dt><dd>Abstract method returning a <code class="docutils literal notranslate"><span class="pre">bool</span></code> that adds the element
<code class="docutils literal notranslate"><span class="pre">x</span></code> if it isnt already in the set. It should return
<code class="docutils literal notranslate"><span class="pre">True</span></code> if <code class="docutils literal notranslate"><span class="pre">x</span></code> was added, <code class="docutils literal notranslate"><span class="pre">False</span></code> if it was already
there. The abstract implementation raises
<code class="docutils literal notranslate"><span class="pre">NotImplementedError</span></code>.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">.discard(x)</span></code></dt><dd>Abstract method returning a <code class="docutils literal notranslate"><span class="pre">bool</span></code> that removes the element
<code class="docutils literal notranslate"><span class="pre">x</span></code> if present. It should return <code class="docutils literal notranslate"><span class="pre">True</span></code> if the element
was present and <code class="docutils literal notranslate"><span class="pre">False</span></code> if it wasnt. The abstract
implementation raises <code class="docutils literal notranslate"><span class="pre">NotImplementedError</span></code>.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">.pop()</span></code></dt><dd>Concrete method that removes and returns an arbitrary item.
If the set is empty, it raises <code class="docutils literal notranslate"><span class="pre">KeyError</span></code>. The default
implementation removes the first item returned by the sets
iterator.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">.toggle(x)</span></code></dt><dd>Concrete method returning a <code class="docutils literal notranslate"><span class="pre">bool</span></code> that adds x to the set if
it wasnt there, but removes it if it was there. It should
return <code class="docutils literal notranslate"><span class="pre">True</span></code> if <code class="docutils literal notranslate"><span class="pre">x</span></code> was added, <code class="docutils literal notranslate"><span class="pre">False</span></code> if it was
removed.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">.clear()</span></code></dt><dd>Concrete method that empties the set. The default
implementation repeatedly calls <code class="docutils literal notranslate"><span class="pre">self.pop()</span></code> until
<code class="docutils literal notranslate"><span class="pre">KeyError</span></code> is caught. (<strong>Note:</strong> this is likely much slower
than simply creating a new set, even if an implementation
overrides it with a faster approach; but in some cases object
identity is important.)</dd>
</dl>
<p>This also supports the in-place mutating operations <code class="docutils literal notranslate"><span class="pre">|=</span></code>,
<code class="docutils literal notranslate"><span class="pre">&amp;=</span></code>, <code class="docutils literal notranslate"><span class="pre">^=</span></code>, <code class="docutils literal notranslate"><span class="pre">-=</span></code>. These are concrete methods whose right
operand can be an arbitrary <code class="docutils literal notranslate"><span class="pre">Iterable</span></code>, except for <code class="docutils literal notranslate"><span class="pre">&amp;=</span></code>, whose
right operand must be a <code class="docutils literal notranslate"><span class="pre">Container</span></code>. This ABC does not provide
the named methods present on the built-in concrete <code class="docutils literal notranslate"><span class="pre">set</span></code> type
that perform (almost) the same operations.</p>
</dd>
</dl>
</section>
<section id="mappings">
<h4><a class="toc-backref" href="#mappings" role="doc-backlink">Mappings</a></h4>
<p>These abstract classes represent read-only mappings and mutable
mappings. The <code class="docutils literal notranslate"><span class="pre">Mapping</span></code> class represents the most common read-only
mapping API.</p>
<p>The built-in type <code class="docutils literal notranslate"><span class="pre">dict</span></code> derives from <code class="docutils literal notranslate"><span class="pre">MutableMapping</span></code>.</p>
<dl>
<dt><code class="docutils literal notranslate"><span class="pre">Mapping</span></code></dt><dd>A subclass of <code class="docutils literal notranslate"><span class="pre">Container</span></code>, <code class="docutils literal notranslate"><span class="pre">Iterable</span></code> and <code class="docutils literal notranslate"><span class="pre">Sized</span></code>. The keys
of a mapping naturally form a set. The (key, value) pairs (which
must be tuples) are also referred to as items. The items also
form a set. Methods:<dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">.__getitem__(key)</span></code></dt><dd>Abstract method that returns the value corresponding to
<code class="docutils literal notranslate"><span class="pre">key</span></code>, or raises <code class="docutils literal notranslate"><span class="pre">KeyError</span></code>. The implementation always
raises <code class="docutils literal notranslate"><span class="pre">KeyError</span></code>.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">.get(key,</span> <span class="pre">default=None)</span></code></dt><dd>Concrete method returning <code class="docutils literal notranslate"><span class="pre">self[key]</span></code> if this does not raise
<code class="docutils literal notranslate"><span class="pre">KeyError</span></code>, and the <code class="docutils literal notranslate"><span class="pre">default</span></code> value if it does.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">.__contains__(key)</span></code></dt><dd>Concrete method returning <code class="docutils literal notranslate"><span class="pre">True</span></code> if <code class="docutils literal notranslate"><span class="pre">self[key]</span></code> does not
raise <code class="docutils literal notranslate"><span class="pre">KeyError</span></code>, and <code class="docutils literal notranslate"><span class="pre">False</span></code> if it does.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">.__len__()</span></code></dt><dd>Abstract method returning the number of distinct keys (i.e.,
the length of the key set).</dd>
<dt><code class="docutils literal notranslate"><span class="pre">.__iter__()</span></code></dt><dd>Abstract method returning each key in the key set exactly once.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">.keys()</span></code></dt><dd>Concrete method returning the key set as a <code class="docutils literal notranslate"><span class="pre">Set</span></code>. The
default concrete implementation returns a “view” on the key
set (meaning if the underlying mapping is modified, the views
value changes correspondingly); subclasses are not required to
return a view but they should return a <code class="docutils literal notranslate"><span class="pre">Set</span></code>.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">.items()</span></code></dt><dd>Concrete method returning the items as a <code class="docutils literal notranslate"><span class="pre">Set</span></code>. The default
concrete implementation returns a “view” on the item set;
subclasses are not required to return a view but they should
return a <code class="docutils literal notranslate"><span class="pre">Set</span></code>.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">.values()</span></code></dt><dd>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.</dd>
</dl>
<p>The following invariants should hold for any mapping <code class="docutils literal notranslate"><span class="pre">m</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">len</span><span class="p">(</span><span class="n">m</span><span class="o">.</span><span class="n">values</span><span class="p">())</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">m</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">m</span><span class="o">.</span><span class="n">items</span><span class="p">())</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
<span class="p">[</span><span class="n">value</span> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">m</span><span class="o">.</span><span class="n">values</span><span class="p">()]</span> <span class="o">==</span> <span class="p">[</span><span class="n">m</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">m</span><span class="o">.</span><span class="n">keys</span><span class="p">()]</span>
<span class="p">[</span><span class="n">item</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">m</span><span class="o">.</span><span class="n">items</span><span class="p">()]</span> <span class="o">==</span> <span class="p">[(</span><span class="n">key</span><span class="p">,</span> <span class="n">m</span><span class="p">[</span><span class="n">key</span><span class="p">])</span> <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">m</span><span class="o">.</span><span class="n">keys</span><span class="p">()]</span>
</pre></div>
</div>
<p>i.e. iterating over the items, keys and values should return
results in the same order.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">MutableMapping</span></code></dt><dd>A subclass of <code class="docutils literal notranslate"><span class="pre">Mapping</span></code> that also implements some standard
mutating methods. Abstract methods include <code class="docutils literal notranslate"><span class="pre">__setitem__</span></code>,
<code class="docutils literal notranslate"><span class="pre">__delitem__</span></code>. Concrete methods include <code class="docutils literal notranslate"><span class="pre">pop</span></code>, <code class="docutils literal notranslate"><span class="pre">popitem</span></code>,
<code class="docutils literal notranslate"><span class="pre">clear</span></code>, <code class="docutils literal notranslate"><span class="pre">update</span></code>. <strong>Note:</strong> <code class="docutils literal notranslate"><span class="pre">setdefault</span></code> is <em>not</em> included.
<strong>Open issues:</strong> Write out the specs for the methods.</dd>
</dl>
</section>
<section id="sequences">
<h4><a class="toc-backref" href="#sequences" role="doc-backlink">Sequences</a></h4>
<p>These abstract classes represent read-only sequences and mutable
sequences.</p>
<p>The built-in <code class="docutils literal notranslate"><span class="pre">list</span></code> and <code class="docutils literal notranslate"><span class="pre">bytes</span></code> types derive from
<code class="docutils literal notranslate"><span class="pre">MutableSequence</span></code>. The built-in <code class="docutils literal notranslate"><span class="pre">tuple</span></code> and <code class="docutils literal notranslate"><span class="pre">str</span></code> types derive
from <code class="docutils literal notranslate"><span class="pre">Sequence</span></code> and <code class="docutils literal notranslate"><span class="pre">Hashable</span></code>.</p>
<dl>
<dt><code class="docutils literal notranslate"><span class="pre">Sequence</span></code></dt><dd>A subclass of <code class="docutils literal notranslate"><span class="pre">Iterable</span></code>, <code class="docutils literal notranslate"><span class="pre">Sized</span></code>, <code class="docutils literal notranslate"><span class="pre">Container</span></code>. It
defines a new abstract method <code class="docutils literal notranslate"><span class="pre">__getitem__</span></code> that has a somewhat
complicated signature: when called with an integer, it returns an
element of the sequence or raises <code class="docutils literal notranslate"><span class="pre">IndexError</span></code>; when called with
a <code class="docutils literal notranslate"><span class="pre">slice</span></code> object, it returns another <code class="docutils literal notranslate"><span class="pre">Sequence</span></code>. The concrete
<code class="docutils literal notranslate"><span class="pre">__iter__</span></code> method iterates over the elements using
<code class="docutils literal notranslate"><span class="pre">__getitem__</span></code> with integer arguments 0, 1, and so on, until
<code class="docutils literal notranslate"><span class="pre">IndexError</span></code> is raised. The length should be equal to the
number of values returned by the iterator.<p><strong>Open issues:</strong> Other candidate methods, which can all have
default concrete implementations that only depend on <code class="docutils literal notranslate"><span class="pre">__len__</span></code>
and <code class="docutils literal notranslate"><span class="pre">__getitem__</span></code> with an integer argument: <code class="docutils literal notranslate"><span class="pre">__reversed__</span></code>,
<code class="docutils literal notranslate"><span class="pre">index</span></code>, <code class="docutils literal notranslate"><span class="pre">count</span></code>, <code class="docutils literal notranslate"><span class="pre">__add__</span></code>, <code class="docutils literal notranslate"><span class="pre">__mul__</span></code>.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">MutableSequence</span></code></dt><dd>A subclass of <code class="docutils literal notranslate"><span class="pre">Sequence</span></code> adding some standard mutating methods.
Abstract mutating methods: <code class="docutils literal notranslate"><span class="pre">__setitem__</span></code> (for integer indices as
well as slices), <code class="docutils literal notranslate"><span class="pre">__delitem__</span></code> (ditto), <code class="docutils literal notranslate"><span class="pre">insert</span></code>. Concrete
mutating methods: <code class="docutils literal notranslate"><span class="pre">append</span></code>, <code class="docutils literal notranslate"><span class="pre">reverse</span></code>, <code class="docutils literal notranslate"><span class="pre">extend</span></code>, <code class="docutils literal notranslate"><span class="pre">pop</span></code>,
<code class="docutils literal notranslate"><span class="pre">remove</span></code>. Concrete mutating operators: <code class="docutils literal notranslate"><span class="pre">+=</span></code>, <code class="docutils literal notranslate"><span class="pre">*=</span></code> (these
mutate the object in place). <strong>Note:</strong> this does not define
<code class="docutils literal notranslate"><span class="pre">sort()</span></code> that is only required to exist on genuine <code class="docutils literal notranslate"><span class="pre">list</span></code>
instances.</dd>
</dl>
</section>
</section>
<section id="strings">
<h3><a class="toc-backref" href="#strings" role="doc-backlink">Strings</a></h3>
<p>Python 3000 will likely have at least two built-in string types: byte
strings (<code class="docutils literal notranslate"><span class="pre">bytes</span></code>), deriving from <code class="docutils literal notranslate"><span class="pre">MutableSequence</span></code>, and (Unicode)
character strings (<code class="docutils literal notranslate"><span class="pre">str</span></code>), deriving from <code class="docutils literal notranslate"><span class="pre">Sequence</span></code> and
<code class="docutils literal notranslate"><span class="pre">Hashable</span></code>.</p>
<p><strong>Open issues:</strong> 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 (<a class="pep reference internal" href="../pep-0358/" title="PEP 358 The “bytes” Object">PEP 358</a> should be co-opted for the
<code class="docutils literal notranslate"><span class="pre">bytes</span></code> type).</p>
</section>
</section>
<section id="abcs-vs-alternatives">
<h2><a class="toc-backref" href="#abcs-vs-alternatives" role="doc-backlink">ABCs vs. Alternatives</a></h2>
<p>In this section I will attempt to compare and contrast ABCs to other
approaches that have been proposed.</p>
<section id="abcs-vs-duck-typing">
<h3><a class="toc-backref" href="#abcs-vs-duck-typing" role="doc-backlink">ABCs vs. Duck Typing</a></h3>
<p>Does the introduction of ABCs mean the end of Duck Typing? I dont
think so. Python will not require that a class derives from
<code class="docutils literal notranslate"><span class="pre">BasicMapping</span></code> or <code class="docutils literal notranslate"><span class="pre">Sequence</span></code> when it defines a <code class="docutils literal notranslate"><span class="pre">__getitem__</span></code>
method, nor will the <code class="docutils literal notranslate"><span class="pre">x[y]</span></code> syntax require that <code class="docutils literal notranslate"><span class="pre">x</span></code> is an instance
of either ABC. You will still be able to assign any “file-like”
object to <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code>, as long as it has a <code class="docutils literal notranslate"><span class="pre">write</span></code> method.</p>
<p>Of course, there will be some carrots to encourage users to derive
from the appropriate base classes; these vary from default
implementations for certain functionality to an improved ability to
distinguish between mappings and sequences. But there are no sticks.
If <code class="docutils literal notranslate"><span class="pre">hasattr(x,</span> <span class="pre">&quot;__len__&quot;)</span></code> works for you, great! ABCs are intended to
solve problems that dont have a good solution at all in Python 2,
such as distinguishing between mappings and sequences.</p>
</section>
<section id="abcs-vs-generic-functions">
<h3><a class="toc-backref" href="#abcs-vs-generic-functions" role="doc-backlink">ABCs vs. Generic Functions</a></h3>
<p>ABCs are compatible with Generic Functions (GFs). For example, my own
Generic Functions implementation <a class="footnote-reference brackets" href="#id14" id="id11">[4]</a> uses the classes (types) of the
arguments as the dispatch key, allowing derived classes to override
base classes. Since (from Pythons perspective) ABCs are quite
ordinary classes, using an ABC in the default implementation for a GF
can be quite appropriate. For example, if I have an overloaded
<code class="docutils literal notranslate"><span class="pre">prettyprint</span></code> function, it would make total sense to define
pretty-printing of sets like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@prettyprint</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">Set</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">pp_set</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
<span class="k">return</span> <span class="s2">&quot;{&quot;</span> <span class="o">+</span> <span class="o">...</span> <span class="o">+</span> <span class="s2">&quot;}&quot;</span> <span class="c1"># Details left as an exercise</span>
</pre></div>
</div>
<p>and implementations for specific subclasses of Set could be added
easily.</p>
<p>I believe ABCs also wont present any problems for RuleDispatch,
Phillip Ebys GF implementation in PEAK <a class="footnote-reference brackets" href="#id15" id="id12">[5]</a>.</p>
<p>Of course, GF proponents might claim that GFs (and concrete, or
implementation, classes) are all you need. But even they will not
deny the usefulness of inheritance; and one can easily consider the
ABCs proposed in this PEP as optional implementation base classes;
there is no requirement that all user-defined mappings derive from
<code class="docutils literal notranslate"><span class="pre">BasicMapping</span></code>.</p>
</section>
<section id="abcs-vs-interfaces">
<h3><a class="toc-backref" href="#abcs-vs-interfaces" role="doc-backlink">ABCs vs. Interfaces</a></h3>
<p>ABCs are not intrinsically incompatible with Interfaces, but there is
considerable overlap. For now, Ill leave it to proponents of
Interfaces to explain why Interfaces are better. I expect that much
of the work that went into e.g. defining the various shades of
“mapping-ness” and the nomenclature could easily be adapted for a
proposal to use Interfaces instead of ABCs.</p>
<p>“Interfaces” in this context refers to a set of proposals for
additional metadata elements attached to a class which are not part of
the regular class hierarchy, but do allow for certain types of
inheritance testing.</p>
<p>Such metadata would be designed, at least in some proposals, so as to
be easily mutable by an application, allowing application writers to
override the normal classification of an object.</p>
<p>The drawback to this idea of attaching mutable metadata to a class is
that classes are shared state, and mutating them may lead to conflicts
of intent. Additionally, the need to override the classification of
an object can be done more cleanly using generic functions: In the
simplest case, one can define a “category membership” generic function
that simply returns False in the base implementation, and then provide
overrides that return True for any classes of interest.</p>
</section>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id13" role="doc-footnote">
<dt class="label" id="id13">[<a href="#id1">1</a>]</dt>
<dd>An Introduction to ABCs, by Talin
(<a class="reference external" href="https://mail.python.org/pipermail/python-3000/2007-April/006614.html">https://mail.python.org/pipermail/python-3000/2007-April/006614.html</a>)</aside>
</aside>
<p>[2] Incomplete implementation prototype, by GvR
(<a class="reference external" href="https://web.archive.org/web/20170223133820/http://svn.python.org/view/sandbox/trunk/abc/">https://web.archive.org/web/20170223133820/http://svn.python.org/view/sandbox/trunk/abc/</a>)</p>
<p>[3] Possible Python 3K Class Tree?, wiki page created by Bill Janssen
(<a class="reference external" href="https://wiki.python.org/moin/AbstractBaseClasses">https://wiki.python.org/moin/AbstractBaseClasses</a>)</p>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id14" role="doc-footnote">
<dt class="label" id="id14">[<a href="#id11">4</a>]</dt>
<dd>Generic Functions implementation, by GvR
(<a class="reference external" href="https://web.archive.org/web/20170223135019/http://svn.python.org/view/sandbox/trunk/overload/">https://web.archive.org/web/20170223135019/http://svn.python.org/view/sandbox/trunk/overload/</a>)</aside>
<aside class="footnote brackets" id="id15" role="doc-footnote">
<dt class="label" id="id15">[<a href="#id12">5</a>]</dt>
<dd>Charming Python: Scaling a new PEAK, by David Mertz
(<a class="reference external" href="https://web.archive.org/web/20070515125102/http://www-128.ibm.com/developerworks/library/l-cppeak2/">https://web.archive.org/web/20070515125102/http://www-128.ibm.com/developerworks/library/l-cppeak2/</a>)</aside>
<aside class="footnote brackets" id="id16" role="doc-footnote">
<dt class="label" id="id16">[<a href="#id5">6</a>]</dt>
<dd>Implementation of &#64;abstractmethod
(<a class="reference external" href="https://github.com/python/cpython/issues/44895">https://github.com/python/cpython/issues/44895</a>)</aside>
<aside class="footnote brackets" id="id17" role="doc-footnote">
<dt class="label" id="id17">[<a href="#id6">7</a>]</dt>
<dd>Unifying types and classes in Python 2.2, by GvR
(<a class="reference external" href="https://www.python.org/download/releases/2.2.3/descrintro/">https://www.python.org/download/releases/2.2.3/descrintro/</a>)</aside>
<aside class="footnote brackets" id="id18" role="doc-footnote">
<dt class="label" id="id18">[<a href="#id7">8</a>]</dt>
<dd>Putting Metaclasses to Work: A New Dimension in Object-Oriented
Programming, by Ira R. Forman and Scott H. Danforth
(<a class="reference external" href="https://archive.org/details/PuttingMetaclassesToWork">https://archive.org/details/PuttingMetaclassesToWork</a>)</aside>
</aside>
<p>[9] Partial order, in Wikipedia
(<a class="reference external" href="https://en.wikipedia.org/wiki/Partial_order">https://en.wikipedia.org/wiki/Partial_order</a>)</p>
<p>[10] Total order, in Wikipedia
(<a class="reference external" href="https://en.wikipedia.org/wiki/Total_order">https://en.wikipedia.org/wiki/Total_order</a>)</p>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id19" role="doc-footnote">
<dt class="label" id="id19">[<a href="#id9">11</a>]</dt>
<dd>Finite set, in Wikipedia
(<a class="reference external" href="https://en.wikipedia.org/wiki/Finite_set">https://en.wikipedia.org/wiki/Finite_set</a>)</aside>
<aside class="footnote brackets" id="id20" role="doc-footnote">
<dt class="label" id="id20">[<a href="#id3">12</a>]</dt>
<dd>Make isinstance/issubclass overloadable
(<a class="reference external" href="https://bugs.python.org/issue1708353">https://bugs.python.org/issue1708353</a>)</aside>
<aside class="footnote brackets" id="id21" role="doc-footnote">
<dt class="label" id="id21">[<a href="#id4">13</a>]</dt>
<dd>ABCMeta sample implementation
(<a class="reference external" href="https://web.archive.org/web/20170224195724/http://svn.python.org/view/sandbox/trunk/abc/xyz.py">https://web.archive.org/web/20170224195724/http://svn.python.org/view/sandbox/trunk/abc/xyz.py</a>)</aside>
<aside class="footnote brackets" id="id22" role="doc-footnote">
<dt class="label" id="id22">[<a href="#id8">14</a>]</dt>
<dd>python-dev email (“Comparing heterogeneous types”)
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2004-June/045111.html">https://mail.python.org/pipermail/python-dev/2004-June/045111.html</a></aside>
<aside class="footnote brackets" id="id23" role="doc-footnote">
<dt class="label" id="id23">[<a href="#id10">15</a>]</dt>
<dd>Function <code class="docutils literal notranslate"><span class="pre">frozenset_hash()</span></code> in Object/setobject.c
(<a class="reference external" href="https://web.archive.org/web/20170224204758/http://svn.python.org/view/python/trunk/Objects/setobject.c">https://web.archive.org/web/20170224204758/http://svn.python.org/view/python/trunk/Objects/setobject.c</a>)</aside>
<aside class="footnote brackets" id="id24" role="doc-footnote">
<dt class="label" id="id24">[<a href="#id2">16</a>]</dt>
<dd>Multiple interpreters in mod_python
(<a class="reference external" href="https://web.archive.org/web/20070515132123/http://www.modpython.org/live/current/doc-html/pyapi-interps.html">https://web.archive.org/web/20070515132123/http://www.modpython.org/live/current/doc-html/pyapi-interps.html</a>)</aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-3119.rst">https://github.com/python/peps/blob/main/peps/pep-3119.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-3119.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a><ul>
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
</ul>
</li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#overloading-isinstance-and-issubclass">Overloading <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> and <code class="docutils literal notranslate"><span class="pre">issubclass()</span></code></a></li>
<li><a class="reference internal" href="#the-abc-module-an-abc-support-framework">The <code class="docutils literal notranslate"><span class="pre">abc</span></code> Module: an ABC Support Framework</a></li>
<li><a class="reference internal" href="#abcs-for-containers-and-iterators">ABCs for Containers and Iterators</a><ul>
<li><a class="reference internal" href="#one-trick-ponies">One Trick Ponies</a></li>
<li><a class="reference internal" href="#sets">Sets</a></li>
<li><a class="reference internal" href="#mappings">Mappings</a></li>
<li><a class="reference internal" href="#sequences">Sequences</a></li>
</ul>
</li>
<li><a class="reference internal" href="#strings">Strings</a></li>
</ul>
</li>
<li><a class="reference internal" href="#abcs-vs-alternatives">ABCs vs. Alternatives</a><ul>
<li><a class="reference internal" href="#abcs-vs-duck-typing">ABCs vs. Duck Typing</a></li>
<li><a class="reference internal" href="#abcs-vs-generic-functions">ABCs vs. Generic Functions</a></li>
<li><a class="reference internal" href="#abcs-vs-interfaces">ABCs vs. Interfaces</a></li>
</ul>
</li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-3119.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>