<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:georss="http://www.georss.org/georss" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0"><id>tag:blogger.com,1999:blog-5440028356946346379</id><updated>2009-07-14T00:46:47.363-04:00</updated><title type="text">Doug Hellmann</title><subtitle type="html">&lt;p&gt;Code Interstices&lt;/p&gt;

&lt;p&gt;All the little things that happen between bouts of coding.  Covering internet technologies, Python, Mac OS X, and open source.&lt;/p&gt;</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.doughellmann.com/search/label/PyMOTW" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/-/PyMOTW/-/PyMOTW?start-index=5&amp;max-results=4" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>126</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>4</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/PyMOTW" type="application/atom+xml" /><feedburner:emailServiceId>PyMOTW</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-2169118471757586548</id><published>2009-07-13T08:53:00.001-04:00</published><updated>2009-07-13T08:53:02.785-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="PyMOTW" /><title type="text">Suggesting PyMOTW topics via Skribit</title><content type="html">I've added a &lt;a href="http://skribit.com/"&gt;Skribit&lt;/a&gt; widget to the &lt;a href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW home page&lt;/a&gt; and to &lt;a href="http://blog.doughellmann.com/"&gt;my blog&lt;/a&gt; to get some feedback from readers about what modules or general topics I should cover next.  Add your suggestion to the list, or vote for one of the existing suggestions, to let me know what you want to read about.  I'll monitor the suggestions and use them to decide which module(s) to start researching for my next article.&lt;br /&gt;&lt;br /&gt;No account is necessary to participate, so let me hear from you today!&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-2169118471757586548?l=blog.doughellmann.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PyMOTW?a=Iaj1-WkzHWQ:oiqoIeS0yv8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PyMOTW?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PyMOTW?a=Iaj1-WkzHWQ:oiqoIeS0yv8:bcOpcFrp8Mo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PyMOTW?d=bcOpcFrp8Mo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PyMOTW?a=Iaj1-WkzHWQ:oiqoIeS0yv8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PyMOTW?i=Iaj1-WkzHWQ:oiqoIeS0yv8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyMOTW/~4/Iaj1-WkzHWQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/2169118471757586548/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=2169118471757586548" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/2169118471757586548" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/2169118471757586548" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyMOTW/~3/Iaj1-WkzHWQ/suggesting-pymotw-topics-via-skribit.html" title="Suggesting PyMOTW topics via Skribit" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="00116818175230541568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.doughellmann.com/2009/07/suggesting-pymotw-topics-via-skribit.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-7271361590908411245</id><published>2009-07-12T08:30:00.001-04:00</published><updated>2009-07-12T08:30:53.727-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="PyMOTW" /><title type="text">PyMOTW: File Access</title><content type="html">&lt;div class="section" id="file-access"&gt;&lt;span id="article-file-access"&gt;&lt;/span&gt;&lt;h1&gt;File Access&lt;/h1&gt;&lt;p&gt;Python&amp;#8217;s standard library includes a large range of tools for working with files, filenames, and file contents.&lt;/p&gt;&lt;div class="section" id="filenames"&gt;&lt;h2&gt;Filenames&lt;/h2&gt;&lt;p&gt;The first step in working with files is to get the name of the file so you can operate on it.  Python represents filenames as simple strings, but provides tools for building them from standard, platform-independent, components in &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;os.path&lt;/span&gt;&lt;/tt&gt;.  List the contents of a directory with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;listdir()&lt;/span&gt;&lt;/tt&gt; from &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;os&lt;/span&gt;&lt;/tt&gt;, or use &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;glob&lt;/span&gt;&lt;/tt&gt; to build a list of filenames from a pattern.  Finer grained filtering of filenames is possible with &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;fnmatch&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="meta-data"&gt;&lt;br /&gt;&lt;h2&gt;Meta-data&lt;/h2&gt;&lt;p&gt;Once you know the name of the file, you may want to check other characteristics such as permissions or the file size using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;os.stat()&lt;/span&gt;&lt;/tt&gt; and the constants in &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;stat&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="reading-files"&gt;&lt;h2&gt;Reading Files&lt;/h2&gt;&lt;p&gt;If you&amp;#8217;re writing a filter application that processes text input line-by-line, &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;fileinput&lt;/span&gt;&lt;/tt&gt; provides an easy framework to get started.  The fileinput API calls for you to iterate over the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;input()&lt;/span&gt;&lt;/tt&gt; generator, processing each line as it is yielded.  The generator handles parsing command line arguments for file names, or falling back to reading directly from &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;sys.stdin&lt;/span&gt;&lt;/tt&gt;.  The result is a flexible tool your users can run directly on a file or as part of a pipeline.&lt;/p&gt;&lt;p&gt;If your app needs random access to files, &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;linecache&lt;/span&gt;&lt;/tt&gt; makes it easy to read lines by their line number.  The contents of the file are maintained in a cache, so be careful of memory consumption.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="temporary-files"&gt;&lt;h2&gt;Temporary Files&lt;/h2&gt;&lt;p&gt;For cases where you need to create scratch files to hold data temporarily, or before moving it to a permanent location, &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;tempfile&lt;/span&gt;&lt;/tt&gt; will be very useful.  It provides classes to create temporary files and directories safely and securely.  Names are guaranteed not to collide, and include random components so they are not easily guessable.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="files-and-directories"&gt;&lt;h2&gt;Files and Directories&lt;/h2&gt;&lt;p&gt;Frequently you need to work on a file as a whole, without worrying about what is in it.  The &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;shutil&lt;/span&gt;&lt;/tt&gt; module includes high-level file operations such as copying files and directories, setting permissions, etc.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The &lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/articles/file_access.html"&gt;canonical version&lt;/a&gt; of this article&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-7271361590908411245?l=blog.doughellmann.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PyMOTW?a=pRdUnTwYNyg:vG4YvTrYNgE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PyMOTW?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PyMOTW?a=pRdUnTwYNyg:vG4YvTrYNgE:bcOpcFrp8Mo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PyMOTW?d=bcOpcFrp8Mo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PyMOTW?a=pRdUnTwYNyg:vG4YvTrYNgE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PyMOTW?i=pRdUnTwYNyg:vG4YvTrYNgE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyMOTW/~4/pRdUnTwYNyg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/7271361590908411245/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=7271361590908411245" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/7271361590908411245" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/7271361590908411245" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyMOTW/~3/pRdUnTwYNyg/pymotw-file-access.html" title="PyMOTW: File Access" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="00116818175230541568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.doughellmann.com/2009/07/pymotw-file-access.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-3102098936979012700</id><published>2009-07-05T09:30:00.001-04:00</published><updated>2009-07-05T09:30:20.015-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="PyMOTW" /><title type="text">New command line interface to PyMOTW</title><content type="html">The &lt;a href="http://www.doughellmann.com/projects/PyMOTW/"&gt;1.95 release of PyMOTW&lt;/a&gt; includes a command line interface to access the documentation for a module.  &lt;br /&gt;&lt;br /&gt;The package can be installed via easy_install or pip:&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;$ pip install PyMOTW&lt;br /&gt;Downloading/unpacking PyMOTW&lt;br /&gt;  Downloading PyMOTW-1.95.tar.gz (2.2Mb): 2.2Mb downloaded&lt;br /&gt;  Running setup.py egg_info for package PyMOTW&lt;br /&gt;    warning: no files found matching 'ChangeLog'&lt;br /&gt;    warning: no files found matching '*.py' under directory 'sphinx/templates'&lt;br /&gt;    no previously-included directories found matching 'utils'&lt;br /&gt;Installing collected packages: PyMOTW&lt;br /&gt;  Running setup.py install for PyMOTW&lt;br /&gt;    changing mode of build/scripts-2.6/motw from 644 to 755&lt;br /&gt;    warning: no files found matching 'ChangeLog'&lt;br /&gt;    warning: no files found matching '*.py' under directory 'sphinx/templates'&lt;br /&gt;    no previously-included directories found matching 'utils'&lt;br /&gt;    changing mode of /Users/dhellmann/.virtualenvs/testpymotw/bin/motw to 755&lt;br /&gt;Successfully installed PyMOTW&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;and then to use the command line interface, run &lt;code&gt;motw&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="syntax"&gt;&lt;pre&gt;$ motw -h&lt;br /&gt;Usage: motw [options] &lt;module_name&gt;&lt;br /&gt;&lt;br /&gt;Options:&lt;br /&gt;  -h, --help  show this help message and exit&lt;br /&gt;  -t, --text  Print plain-text version of help to stdout&lt;br /&gt;  -w, --web   Open HTML version of help from web&lt;br /&gt;  --html      Open HTML version of help from installed file&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;For example, &lt;code&gt;motw abc&lt;/code&gt; opens the local version of &lt;a href="http://blog.doughellmann.com/2009/07/pymotw-abc-abstract-base-classes.html"&gt;this week's article&lt;/a&gt;.  You can also use the "-w" option to go to my web site instead of reading the local version, so you always have the latest version of an article.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-3102098936979012700?l=blog.doughellmann.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PyMOTW?a=GyMEOtJNpRc:ZhP1SVJCDWc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PyMOTW?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PyMOTW?a=GyMEOtJNpRc:ZhP1SVJCDWc:bcOpcFrp8Mo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PyMOTW?d=bcOpcFrp8Mo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PyMOTW?a=GyMEOtJNpRc:ZhP1SVJCDWc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PyMOTW?i=GyMEOtJNpRc:ZhP1SVJCDWc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyMOTW/~4/GyMEOtJNpRc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/3102098936979012700/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=3102098936979012700" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/3102098936979012700" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/3102098936979012700" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyMOTW/~3/GyMEOtJNpRc/new-command-line-interface-to-pymotw.html" title="New command line interface to PyMOTW" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="00116818175230541568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://blog.doughellmann.com/2009/07/new-command-line-interface-to-pymotw.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-5440028356946346379.post-257613817223471603</id><published>2009-07-05T09:18:00.001-04:00</published><updated>2009-07-05T09:18:48.519-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="PyMOTW" /><title type="text">PyMOTW: abc - Abstract Base Classes</title><content type="html">&lt;div class="section" id="module-abc"&gt;&lt;h1&gt;abc &amp;#8211; Abstract Base Classes&lt;/h1&gt;&lt;table class="docutils field-list" frame="void" rules="none"&gt;&lt;col class="field-name"&gt;&lt;/col&gt;&lt;col class="field-body"&gt;&lt;/col&gt;&lt;tbody valign="top"&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Purpose:&lt;/th&gt;&lt;td class="field-body"&gt;Define and use abstract base classes for API checks in your code.&lt;/td&gt;&lt;/tr&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Python Version:&lt;/th&gt;&lt;td class="field-body"&gt;2.6&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="section" id="why-use-abstract-base-classes"&gt;&lt;br /&gt;&lt;h2&gt;Why use Abstract Base Classes?&lt;/h2&gt;&lt;p&gt;Abstract base classes are a form of interface checking more strict than individual &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;hasattr()&lt;/span&gt;&lt;/tt&gt; checks for particular methods.  By defining an abstract base class, you can define a common API for a set of subclasses.  This capability is especially useful in situations where a third-party is going to provide implementations, such as with plugins to an application, but can also aid you when working on a large team or with a large code-base where keeping all classes in your head at the same time is difficult or not possible.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="how-abcs-work"&gt;&lt;h2&gt;How ABCs Work&lt;/h2&gt;&lt;p&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;abc&lt;/span&gt;&lt;/tt&gt; works by marking methods of the base class as abstract, and then registering concrete classes as implementations of the abstract base.  If your code requires a particular API, you can use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;issubclass()&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;isinstance()&lt;/span&gt;&lt;/tt&gt; to check an object against the abstract class.&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s start by defining an abstract base class to represent the API of a set of plugins for saving and loading data.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;__metaclass__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ABCMeta&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractmethod&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Retrieve data from the input source and return an object.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractmethod&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Save the data object to the output.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="registering-a-concrete-class"&gt;&lt;h2&gt;Registering a Concrete Class&lt;/h2&gt;&lt;p&gt;There are two ways to indicate that a concrete class implements an abstract: register the class with the abc or subclass directly from the abc.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;abc_base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegisteredImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RegisteredImplementation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Subclass:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;issubclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RegisteredImplementation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Instance:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RegisteredImplementation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;In this example the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PluginImplementation&lt;/span&gt;&lt;/tt&gt; is not derived from &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PluginBase&lt;/span&gt;&lt;/tt&gt;, but is registered as implementing the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PluginBase&lt;/span&gt;&lt;/tt&gt; API.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_register.py&lt;br /&gt;Subclass: True&lt;br /&gt;Instance: True&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="implementation-through-subclassing"&gt;&lt;h2&gt;Implementation Through Subclassing&lt;/h2&gt;&lt;p&gt;By subclassing directly from the base, we can avoid the need to register the class explicitly.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;abc_base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SubclassImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Subclass:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;issubclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SubclassImplementation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Instance:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SubclassImplementation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;In this case the normal Python class management is used to recognize &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PluginImplementation&lt;/span&gt;&lt;/tt&gt; as implementing the abstract &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PluginBase&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_subclass.py&lt;br /&gt;Subclass: True&lt;br /&gt;Instance: True&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;A side-effect of using direct subclassing is it is possible to find all of the implementations of your plugin by asking the base class for the list of known classes derived from it (this is not an abc feature, all classes can do this).&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;abc_base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc_subclass&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc_register&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__subclasses__&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;sc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Notice that even though &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;abc_register&lt;/span&gt;&lt;/tt&gt; is imported, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;RegisteredImplementation&lt;/span&gt;&lt;/tt&gt; is not among the list of subclasses because it is not actually derived from the base.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_find_subclasses.py&lt;br /&gt;SubclassImplementation&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Dr. Andr√© Roberge &lt;a class="reference external" href="http://us.pycon.org/2009/conference/schedule/event/47/"&gt;has described&lt;/a&gt; using this capability to discover plugins by importing all of the modules in a directory dynamically and then looking at the subclass list to find the implementation classes.&lt;/p&gt;&lt;div class="section" id="incomplete-implementations"&gt;&lt;h3&gt;Incomplete Implementations&lt;/h3&gt;&lt;p&gt;Another benefit of subclassing directly from your abstract base class is that the subclass cannot be instantiated unless it fully implements the abstract portion of the API.  This can keep half-baked implementations from triggering unexpected errors at runtime.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;abc_base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IncompleteImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IncompleteImplementation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Subclass:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;issubclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IncompleteImplementation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Instance:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IncompleteImplementation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;PluginBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_incomplete.py&lt;br /&gt;Subclass: True&lt;br /&gt;Instance:&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "abc_incomplete.py", line 22, in &amp;lt;module&amp;gt;&lt;br /&gt;    print 'Instance:', isinstance(IncompleteImplementation(), PluginBase)&lt;br /&gt;TypeError: Can't instantiate abstract class IncompleteImplementation with abstract methods load&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="concrete-methods-in-abcs"&gt;&lt;h2&gt;Concrete Methods in ABCs&lt;/h2&gt;&lt;p&gt;Although a concrete class must provide an implementation of an abstract methods, the abstract base class can also provide an implementation that can be invoked via &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;super()&lt;/span&gt;&lt;/tt&gt;.  This lets you re-use common logic by placing it in the base class, but force subclasses to provide an overriding method with (potentially) custom logic.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;cStringIO&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StringIO&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ABCWithConcreteImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;__metaclass__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ABCMeta&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractmethod&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;base class reading data&amp;#39;&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConcreteOverride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ABCWithConcreteImplementation&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;base_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ConcreteOverride&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retrieve_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;subclass sorting data&amp;#39;&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="nb"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StringIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&amp;quot;line one&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;line two&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;line three&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConcreteOverride&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retrieve_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Since &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ABCWithConcreteImplementation&lt;/span&gt;&lt;/tt&gt; is an abstract base class, it isn&amp;#8217;t possible to instantiate it to use it directly.  Subclasses &lt;em&gt;must&lt;/em&gt; provide an override for &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;retrieve_values()&lt;/span&gt;&lt;/tt&gt;, and in this case the concrete class massages the data before returning it at all.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_concrete_method.py&lt;br /&gt;base class reading data&lt;br /&gt;subclass sorting data&lt;br /&gt;['line one', 'line three', 'line two']&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="abstract-properties"&gt;&lt;h2&gt;Abstract Properties&lt;/h2&gt;&lt;p&gt;If your API specification includes attributes in addition to methods, you can require the attributes in concrete classes by defining them with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;&amp;#64;abstractproperty&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;__metaclass__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ABCMeta&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractproperty&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Should never get here&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@property&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;concrete property&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Base.value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ERROR:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Implementation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Implementation.value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Base&lt;/span&gt;&lt;/tt&gt; class in the example cannot be instantiated because it has only an abstract version of the property getter method.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_abstractproperty.py&lt;br /&gt;ERROR: Can't instantiate abstract class Base with abstract methods value&lt;br /&gt;Implementation.value: concrete property&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;You can also define abstract read/write properties.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;__metaclass__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ABCMeta&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value_getter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Should never see this&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value_setter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newvalue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractproperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value_getter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value_setter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PartialImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractproperty&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Read-only&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Default value&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value_getter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_value&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value_setter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newvalue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newvalue&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value_getter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value_setter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Base.value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ERROR:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PartialImplementation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;PartialImplementation.value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;ERROR:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Implementation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Implementation.value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;New value&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Changed value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Notice that the concrete property must be defined the same way as the abstract property.  Trying to override a read/write property in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PartialImplementation&lt;/span&gt;&lt;/tt&gt; with one that is read-only does not work.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_abstractproperty_rw.py&lt;br /&gt;ERROR: Can't instantiate abstract class Base with abstract methods value&lt;br /&gt;ERROR: Can't instantiate abstract class PartialImplementation with abstract methods value&lt;br /&gt;Implementation.value: Default value&lt;br /&gt;Changed value: New value&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Unfortunately, the decorator syntax does not work for read/write abstract properties the way it does with concrete properties.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;abc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;__metaclass__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ABCMeta&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractproperty&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Should never see this&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setter&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value_setter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newvalue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="n"&gt;_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Default value&amp;#39;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="nd"&gt;@property&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_value&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="nd"&gt;@value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setter&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;value_setter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newvalue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newvalue&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Implementation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Implementation.value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;New value&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Changed value:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Notice that the caller cannot set the property value.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python abc_abstractproperty_rw_deco.py&lt;br /&gt;Implementation.value: Default value&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "abc_abstractproperty_rw_deco.py", line 40, in &amp;lt;module&amp;gt;&lt;br /&gt;    i.value = 'New value'&lt;br /&gt;AttributeError: can't set attribute&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="collection-types"&gt;&lt;h2&gt;Collection Types&lt;/h2&gt;&lt;p&gt;The &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;collections&lt;/span&gt;&lt;/tt&gt; module defines several abstract base classes related to container (and containable) types.&lt;/p&gt;&lt;p&gt;General container classes:&lt;/p&gt;&lt;ul class="simple"&gt;&lt;li&gt;Container&lt;/li&gt;&lt;li&gt;Sized&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Iterator and Sequence classes:&lt;/p&gt;&lt;ul class="simple"&gt;&lt;li&gt;Iterable&lt;/li&gt;&lt;li&gt;Iterator&lt;/li&gt;&lt;li&gt;Sequence&lt;/li&gt;&lt;li&gt;MutableSequence&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Unique values:&lt;/p&gt;&lt;ul class="simple"&gt;&lt;li&gt;Hashable&lt;/li&gt;&lt;li&gt;Set&lt;/li&gt;&lt;li&gt;MutableSet&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Mappings:&lt;/p&gt;&lt;ul class="simple"&gt;&lt;li&gt;Mapping&lt;/li&gt;&lt;li&gt;MutableMapping&lt;/li&gt;&lt;li&gt;MappingView&lt;/li&gt;&lt;li&gt;KeysView&lt;/li&gt;&lt;li&gt;ItemsView&lt;/li&gt;&lt;li&gt;ValuesView&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Miscelaneous:&lt;/p&gt;&lt;ul class="simple"&gt;&lt;li&gt;Callable&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In addition to serving as detailed real-world examples of abstract base classes, Python&amp;#8217;s built-in types are automatically registered to these classes when you import &lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;collections&lt;/span&gt;&lt;/tt&gt;. This means you can safely use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;isinstance()&lt;/span&gt;&lt;/tt&gt; to check parameters in your code to ensure that they support the API you need.  The base classes can also be used to define your own collection types, since many of them provide concrete implementations of the internals and only need a few methods overridden.  Refer to the standard library docs for collections for more details.&lt;/p&gt;&lt;div class="admonition-see-also admonition seealso"&gt;&lt;p class="first admonition-title"&gt;See also&lt;/p&gt;&lt;dl class="last docutils"&gt;&lt;dt&gt;&lt;a class="reference external" href="http://docs.python.org/library/abc.html"&gt;abc&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;The standard library documentation for this module.&lt;/dd&gt;&lt;dt&gt;&lt;span class="target" id="index-0"&gt;&lt;/span&gt;&lt;a class="reference external" href="http://www.python.org/dev/peps/pep-3119"&gt;&lt;strong&gt;PEP 3119&lt;/strong&gt;&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;Introducing Abstract Base Classes&lt;/dd&gt;&lt;dt&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;collections&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;The collections module includes abstract base classes for several collection types.&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://docs.python.org/library/collections.html"&gt;collections&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;The standard library documentation for collections.&lt;/dd&gt;&lt;dt&gt;&lt;span class="target" id="index-1"&gt;&lt;/span&gt;&lt;a class="reference external" href="http://www.python.org/dev/peps/pep-3141"&gt;&lt;strong&gt;PEP 3141&lt;/strong&gt;&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;A Type Hierarchy for Numbers&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://en.wikipedia.org/wiki/Strategy_pattern"&gt;Wikipedia: Strategy Pattern&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;Description and examples of the strategy pattern.&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://us.pycon.org/2009/conference/schedule/event/47/"&gt;Plugins and monkeypatching&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;PyCon 2009 presentation by Dr. Andr√© Roberge&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The &lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/abc/"&gt;canonical version&lt;/a&gt; of this article&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-257613817223471603?l=blog.doughellmann.com'/&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PyMOTW?a=ODkF38FFsm8:3ObQbYJFug8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PyMOTW?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PyMOTW?a=ODkF38FFsm8:3ObQbYJFug8:bcOpcFrp8Mo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PyMOTW?d=bcOpcFrp8Mo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PyMOTW?a=ODkF38FFsm8:3ObQbYJFug8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PyMOTW?i=ODkF38FFsm8:3ObQbYJFug8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PyMOTW/~4/ODkF38FFsm8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/257613817223471603/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=257613817223471603" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/257613817223471603" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/257613817223471603" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PyMOTW/~3/ODkF38FFsm8/pymotw-abc-abstract-base-classes.html" title="PyMOTW: abc - Abstract Base Classes" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="00116818175230541568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://blog.doughellmann.com/2009/07/pymotw-abc-abstract-base-classes.html</feedburner:origLink></entry></feed>
