summaryrefslogtreecommitdiff
path: root/pypers/oxford/all.html
diff options
context:
space:
mode:
Diffstat (limited to 'pypers/oxford/all.html')
-rwxr-xr-xpypers/oxford/all.html2366
1 files changed, 0 insertions, 2366 deletions
diff --git a/pypers/oxford/all.html b/pypers/oxford/all.html
deleted file mode 100755
index 56f2314..0000000
--- a/pypers/oxford/all.html
+++ /dev/null
@@ -1,2366 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="generator" content="Docutils 0.3.10: http://docutils.sourceforge.net/" />
-<title>Lectures on Advanced Python Programming</title>
-<style type="text/css">
-
-/*
-:Author: David Goodger
-:Contact: goodger@users.sourceforge.net
-:Date: $Date: 2005-06-06 15:09:07 +0200 (Mon, 06 Jun 2005) $
-:Version: $Revision: 3442 $
-:Copyright: This stylesheet has been placed in the public domain.
-
-Default cascading style sheet for the HTML output of Docutils.
-*/
-
-/* "! important" is used here to override other ``margin-top`` and
- ``margin-bottom`` styles that are later in the stylesheet or
- more specific. See http://www.w3.org/TR/CSS1#the-cascade */
-.first {
- margin-top: 0 ! important }
-
-.last, .with-subtitle {
- margin-bottom: 0 ! important }
-
-.hidden {
- display: none }
-
-a.toc-backref {
- text-decoration: none ;
- color: black }
-
-blockquote.epigraph {
- margin: 2em 5em ; }
-
-dl.docutils dd {
- margin-bottom: 0.5em }
-
-/* Uncomment (and remove this text!) to get bold-faced definition list terms
-dl.docutils dt {
- font-weight: bold }
-*/
-
-div.abstract {
- margin: 2em 5em }
-
-div.abstract p.topic-title {
- font-weight: bold ;
- text-align: center }
-
-div.admonition, div.attention, div.caution, div.danger, div.error,
-div.hint, div.important, div.note, div.tip, div.warning {
- margin: 2em ;
- border: medium outset ;
- padding: 1em }
-
-div.admonition p.admonition-title, div.hint p.admonition-title,
-div.important p.admonition-title, div.note p.admonition-title,
-div.tip p.admonition-title {
- font-weight: bold ;
- font-family: sans-serif }
-
-div.attention p.admonition-title, div.caution p.admonition-title,
-div.danger p.admonition-title, div.error p.admonition-title,
-div.warning p.admonition-title {
- color: red ;
- font-weight: bold ;
- font-family: sans-serif }
-
-/* Uncomment (and remove this text!) to get reduced vertical space in
- compound paragraphs.
-div.compound .compound-first, div.compound .compound-middle {
- margin-bottom: 0.5em }
-
-div.compound .compound-last, div.compound .compound-middle {
- margin-top: 0.5em }
-*/
-
-div.dedication {
- margin: 2em 5em ;
- text-align: center ;
- font-style: italic }
-
-div.dedication p.topic-title {
- font-weight: bold ;
- font-style: normal }
-
-div.figure {
- margin-left: 2em }
-
-div.footer, div.header {
- clear: both;
- font-size: smaller }
-
-div.line-block {
- display: block ;
- margin-top: 1em ;
- margin-bottom: 1em }
-
-div.line-block div.line-block {
- margin-top: 0 ;
- margin-bottom: 0 ;
- margin-left: 1.5em }
-
-div.sidebar {
- margin-left: 1em ;
- border: medium outset ;
- padding: 1em ;
- background-color: #ffffee ;
- width: 40% ;
- float: right ;
- clear: right }
-
-div.sidebar p.rubric {
- font-family: sans-serif ;
- font-size: medium }
-
-div.system-messages {
- margin: 5em }
-
-div.system-messages h1 {
- color: red }
-
-div.system-message {
- border: medium outset ;
- padding: 1em }
-
-div.system-message p.system-message-title {
- color: red ;
- font-weight: bold }
-
-div.topic {
- margin: 2em }
-
-h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
-h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
- margin-top: 0.4em }
-
-h1.title {
- text-align: center }
-
-h2.subtitle {
- text-align: center }
-
-hr.docutils {
- width: 75% }
-
-img.align-left {
- clear: left }
-
-img.align-right {
- clear: right }
-
-img.borderless {
- border: 0 }
-
-ol.simple, ul.simple {
- margin-bottom: 1em }
-
-ol.arabic {
- list-style: decimal }
-
-ol.loweralpha {
- list-style: lower-alpha }
-
-ol.upperalpha {
- list-style: upper-alpha }
-
-ol.lowerroman {
- list-style: lower-roman }
-
-ol.upperroman {
- list-style: upper-roman }
-
-p.attribution {
- text-align: right ;
- margin-left: 50% }
-
-p.caption {
- font-style: italic }
-
-p.credits {
- font-style: italic ;
- font-size: smaller }
-
-p.label {
- white-space: nowrap }
-
-p.rubric {
- font-weight: bold ;
- font-size: larger ;
- color: maroon ;
- text-align: center }
-
-p.sidebar-title {
- font-family: sans-serif ;
- font-weight: bold ;
- font-size: larger }
-
-p.sidebar-subtitle {
- font-family: sans-serif ;
- font-weight: bold }
-
-p.topic-title {
- font-weight: bold }
-
-pre.address {
- margin-bottom: 0 ;
- margin-top: 0 ;
- font-family: serif ;
- font-size: 100% }
-
-pre.line-block {
- font-family: serif ;
- font-size: 100% }
-
-pre.literal-block, pre.doctest-block {
- margin-left: 2em ;
- margin-right: 2em ;
- background-color: #eeeeee }
-
-span.classifier {
- font-family: sans-serif ;
- font-style: oblique }
-
-span.classifier-delimiter {
- font-family: sans-serif ;
- font-weight: bold }
-
-span.interpreted {
- font-family: sans-serif }
-
-span.option {
- white-space: nowrap }
-
-span.pre {
- white-space: pre }
-
-span.problematic {
- color: red }
-
-span.section-subtitle {
- /* font-size relative to parent (h1..h6 element) */
- font-size: 80% }
-
-table.citation {
- border-left: solid thin gray }
-
-table.docinfo {
- margin: 2em 4em }
-
-table.docutils {
- margin-top: 0.5em ;
- margin-bottom: 0.5em }
-
-table.footnote {
- border-left: solid thin black }
-
-table.docutils td, table.docutils th,
-table.docinfo td, table.docinfo th {
- padding-left: 0.5em ;
- padding-right: 0.5em ;
- vertical-align: top }
-
-table.docutils th.field-name, table.docinfo th.docinfo-name {
- font-weight: bold ;
- text-align: left ;
- white-space: nowrap ;
- padding-left: 0 }
-
-h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
-h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
- font-size: 100% }
-
-tt.docutils {
- background-color: #eeeeee }
-
-ul.auto-toc {
- list-style-type: none }
-
-</style>
-</head>
-<body>
-<div class="document" id="lectures-on-advanced-python-programming">
-<h1 class="title">Lectures on Advanced Python Programming</h1>
-<img alt="accu2005.png" src="accu2005.png" />
-<table class="docutils field-list" frame="void" rules="none">
-<col class="field-name" />
-<col class="field-body" />
-<tbody valign="top">
-<tr class="field"><th class="field-name">Author:</th><td class="field-body">Michele Simionato</td>
-</tr>
-<tr class="field"><th class="field-name">Given:</th><td class="field-body">19 April 2005</td>
-</tr>
-<tr class="field"><th class="field-name">Revised:</th><td class="field-body">7 September 2005</td>
-</tr>
-</tbody>
-</table>
-<div class="contents topic" id="contents">
-<p class="topic-title first"><a name="contents">Contents</a></p>
-<ul class="simple">
-<li><a class="reference" href="#lecture-1-loops-i-e-iterators-generators" id="id1" name="id1">Lecture 1: Loops (i.e. iterators &amp; generators)</a><ul>
-<li><a class="reference" href="#part-i-iterators" id="id2" name="id2">Part I: iterators</a><ul>
-<li><a class="reference" href="#iterators-are-everywhere" id="id3" name="id3">Iterators are everywhere</a></li>
-<li><a class="reference" href="#iterables-and-iterators" id="id4" name="id4">Iterables and iterators</a></li>
-<li><a class="reference" href="#simpler-way-to-get-an-iterator" id="id5" name="id5">Simpler way to get an iterator</a></li>
-<li><a class="reference" href="#sentinel-syntax-iter-callable-sentinel" id="id6" name="id6">Sentinel syntax iter(callable, sentinel)</a></li>
-<li><a class="reference" href="#second-simpler-way-to-get-an-iterator-generator-expressions" id="id7" name="id7">Second simpler way to get an iterator: generator-expressions</a></li>
-<li><a class="reference" href="#iteration-caveats" id="id8" name="id8">Iteration caveats</a></li>
-</ul>
-</li>
-<li><a class="reference" href="#part-ii-generators" id="id9" name="id9">Part II: generators</a><ul>
-<li><a class="reference" href="#a-simple-recipe-skip-redundant" id="id10" name="id10">A simple recipe: skip redundant</a></li>
-<li><a class="reference" href="#another-real-life-example-working-with-nested-structures" id="id11" name="id11">Another real life example: working with nested structures</a></li>
-<li><a class="reference" href="#another-typical-use-case-for-generators-parsers" id="id12" name="id12">Another typical use case for generators: parsers</a></li>
-<li><a class="reference" href="#other-kinds-of-iterables" id="id13" name="id13">Other kinds of iterables</a></li>
-<li><a class="reference" href="#the-itertools-module" id="id14" name="id14">The itertools module</a></li>
-<li><a class="reference" href="#anytrue" id="id15" name="id15">anyTrue</a></li>
-<li><a class="reference" href="#chop" id="id16" name="id16">chop</a></li>
-<li><a class="reference" href="#tee" id="id17" name="id17">tee</a></li>
-<li><a class="reference" href="#grouping-and-sorting" id="id18" name="id18">Grouping and sorting</a></li>
-</ul>
-</li>
-</ul>
-</li>
-<li><a class="reference" href="#lecture-2-objects-delegation-inheritance" id="id19" name="id19">Lecture 2: Objects (delegation &amp; inheritance)</a><ul>
-<li><a class="reference" href="#part-i-delegation" id="id20" name="id20">Part I: delegation</a><ul>
-<li><a class="reference" href="#accessing-simple-attributes" id="id21" name="id21">Accessing simple attributes</a></li>
-<li><a class="reference" href="#accessing-methods" id="id22" name="id22">Accessing methods</a></li>
-<li><a class="reference" href="#converting-functions-into-methods" id="id23" name="id23">Converting functions into methods</a></li>
-<li><a class="reference" href="#hack-a-very-slick-adder" id="id24" name="id24">Hack: a very slick adder</a></li>
-<li><a class="reference" href="#descriptor-protocol" id="id25" name="id25">Descriptor Protocol</a></li>
-<li><a class="reference" href="#multilingual-attribute" id="id26" name="id26">Multilingual attribute</a></li>
-<li><a class="reference" href="#another-use-case-for-properties-storing-users" id="id27" name="id27">Another use case for properties: storing users</a></li>
-<li><a class="reference" href="#low-level-delegation-via-getattribute" id="id28" name="id28">Low-level delegation via __getattribute__</a></li>
-<li><a class="reference" href="#traditional-delegation-via-getattr" id="id29" name="id29">Traditional delegation via __getattr__</a></li>
-<li><a class="reference" href="#keyword-dictionaries-with-getattr-setattr" id="id30" name="id30">Keyword dictionaries with __getattr__/__setattr__</a></li>
-<li><a class="reference" href="#delegation-to-special-methods-caveat" id="id31" name="id31">Delegation to special methods caveat</a></li>
-</ul>
-</li>
-<li><a class="reference" href="#part-ii-inheritance" id="id32" name="id32">Part II: Inheritance</a><ul>
-<li><a class="reference" href="#why-you-need-to-know-about-mi-even-if-you-do-not-use-it" id="id33" name="id33">Why you need to know about MI even if you do not use it</a></li>
-<li><a class="reference" href="#a-few-details-about-super-not-the-whole-truth" id="id34" name="id34">A few details about <tt class="docutils literal"><span class="pre">super</span></tt> (not the whole truth)</a></li>
-<li><a class="reference" href="#subclassing-built-in-types-new-vs-init" id="id35" name="id35">Subclassing built-in types; __new__ vs. __init__</a></li>
-<li><a class="reference" href="#be-careful-when-using-new-with-mutable-types" id="id36" name="id36">Be careful when using __new__ with mutable types</a></li>
-</ul>
-</li>
-</ul>
-</li>
-<li><a class="reference" href="#lecture-3-magic-i-e-decorators-and-metaclasses" id="id37" name="id37">Lecture 3: Magic (i.e. decorators and metaclasses)</a><ul>
-<li><a class="reference" href="#part-i-decorators" id="id38" name="id38">Part I: decorators</a><ul>
-<li><a class="reference" href="#a-typical-decorator-traced" id="id39" name="id39">A typical decorator: traced</a></li>
-<li><a class="reference" href="#a-decorator-factory-timed" id="id40" name="id40">A decorator factory: Timed</a></li>
-<li><a class="reference" href="#a-powerful-decorator-pattern" id="id41" name="id41">A powerful decorator pattern</a></li>
-<li><a class="reference" href="#a-deferred-decorator" id="id42" name="id42">A deferred decorator</a></li>
-</ul>
-</li>
-<li><a class="reference" href="#part-ii-metaclasses" id="id43" name="id43">Part II: metaclasses</a><ul>
-<li><a class="reference" href="#rejuvenating-old-style-classes" id="id44" name="id44">Rejuvenating old-style classes</a></li>
-<li><a class="reference" href="#a-typical-metaclass-example-metatracer" id="id45" name="id45">A typical metaclass example: MetaTracer</a></li>
-<li><a class="reference" href="#real-life-example-check-overriding" id="id46" name="id46">Real life example: check overriding</a></li>
-<li><a class="reference" href="#logfile" id="id47" name="id47">LogFile</a></li>
-<li><a class="reference" href="#cooperative-hierarchies" id="id48" name="id48">Cooperative hierarchies</a></li>
-<li><a class="reference" href="#metaclass-enhanced-modules" id="id49" name="id49">Metaclass-enhanced modules</a></li>
-<li><a class="reference" href="#magic-properties" id="id50" name="id50">Magic properties</a></li>
-<li><a class="reference" href="#hack-evil-properties" id="id51" name="id51">Hack: evil properties</a></li>
-<li><a class="reference" href="#why-i-suggest-not-to-use-metaclasses-in-production-code" id="id52" name="id52">Why I suggest <em>not</em> to use metaclasses in production code</a></li>
-<li><a class="reference" href="#is-there-an-automatic-way-of-solving-the-conflict" id="id53" name="id53">Is there an automatic way of solving the conflict?</a></li>
-</ul>
-</li>
-</ul>
-</li>
-</ul>
-</div>
-<div class="section" id="lecture-1-loops-i-e-iterators-generators">
-<h1><a class="toc-backref" href="#id1" name="lecture-1-loops-i-e-iterators-generators">Lecture 1: Loops (i.e. iterators &amp; generators)</a></h1>
-<div class="section" id="part-i-iterators">
-<h2><a class="toc-backref" href="#id2" name="part-i-iterators">Part I: iterators</a></h2>
-<div class="section" id="iterators-are-everywhere">
-<h3><a class="toc-backref" href="#id3" name="iterators-are-everywhere">Iterators are everywhere</a></h3>
-<pre class="doctest-block">
-&gt;&gt;&gt; for i in 1, 2, 3:
-... print i
-1
-2
-3
-</pre>
-<p>The 'for' loop is using <em>iterators</em> internally:</p>
-<pre class="literal-block">
-it = iter((1,2,3))
-while True:
- try:
- print it.next()
- except StopIteration:
- break
-</pre>
-</div>
-<div class="section" id="iterables-and-iterators">
-<h3><a class="toc-backref" href="#id4" name="iterables-and-iterators">Iterables and iterators</a></h3>
-<p><em>Iterable</em> = anything you can loop over = any sequence + any object with an __iter__ method;</p>
-<p>Not every sequence has an __iter__ method:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; &quot;hello&quot;.__iter__()
-Traceback (most recent call last):
- ...
-AttributeError: 'str' object has no attribute '__iter__'
-</pre>
-<p><em>Iterator</em> = any object with a .next method and an __iter__ method returning self</p>
-</div>
-<div class="section" id="simpler-way-to-get-an-iterator">
-<h3><a class="toc-backref" href="#id5" name="simpler-way-to-get-an-iterator">Simpler way to get an iterator</a></h3>
-<pre class="doctest-block">
-&gt;&gt;&gt; it = iter(&quot;hello&quot;)
-&gt;&gt;&gt; it.next()
-'h'
-&gt;&gt;&gt; it.next()
-'e'
-&gt;&gt;&gt; it.next()
-'l'
-&gt;&gt;&gt; it.next()
-'l'
-&gt;&gt;&gt; it.next()
-'o'
-&gt;&gt;&gt; it.next()
-Traceback (most recent call last):
- ...
-StopIteration
-</pre>
-</div>
-<div class="section" id="sentinel-syntax-iter-callable-sentinel">
-<h3><a class="toc-backref" href="#id6" name="sentinel-syntax-iter-callable-sentinel">Sentinel syntax iter(callable, sentinel)</a></h3>
-<p>Example:</p>
-<pre class="literal-block">
-$ echo -e &quot;value1\nvalue2\nEND\n&quot; &gt; data.txt
-$ python -c &quot;print list(iter(file('data.txt').readline, 'END\n'))&quot;
-['value1\n', 'value2\n']
-</pre>
-<p>Beware of infinite iterators:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; repeat = iter(lambda : &quot;some value&quot;, &quot;&quot;)
-&gt;&gt;&gt; repeat.next()
-'some value'
-</pre>
-</div>
-<div class="section" id="second-simpler-way-to-get-an-iterator-generator-expressions">
-<h3><a class="toc-backref" href="#id7" name="second-simpler-way-to-get-an-iterator-generator-expressions">Second simpler way to get an iterator: generator-expressions</a></h3>
-<pre class="doctest-block">
-&gt;&gt;&gt; squares = (i*i for i in range(1,11))
-&gt;&gt;&gt; list(squares)
-[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
-</pre>
-<p>Excessive parenthesis can be skipped, so use</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; dict((i, i*i) for i in range(1,11))
-{1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100}
-</pre>
-<p>instead of</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; dict([(i, i*i) for i in range(1,11)])
-{1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100}
-</pre>
-<p>(as usual, the most elegant version is the most efficient).</p>
-</div>
-<div class="section" id="iteration-caveats">
-<h3><a class="toc-backref" href="#id8" name="iteration-caveats">Iteration caveats</a></h3>
-<pre class="doctest-block">
-&gt;&gt;&gt; ls = [i for i in (1,2,3)]
-&gt;&gt;&gt; i
-3
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; it = (j for j in (1,2,3))
-&gt;&gt;&gt; j
-Traceback (most recent call last):
- ...
-NameError: name 'j' is not defined
-</pre>
-<p>A subtler example:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; ls = [lambda :i for i in (1,2,3)]
-&gt;&gt;&gt; ls[0]()
-3
-</pre>
-<p>instead</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; it = (lambda :i for i in (1,2,3))
-&gt;&gt;&gt; it.next()()
-1
-&gt;&gt;&gt; it.next()()
-2
-&gt;&gt;&gt; it.next()()
-3
-</pre>
-<p><em>seems</em> to be working but it is not really the case:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; it = (lambda :i for i in (1,2,3))
-&gt;&gt;&gt; f1 = it.next()
-&gt;&gt;&gt; f2 = it.next()
-&gt;&gt;&gt; f3 = it.next()
-&gt;&gt;&gt; f1()
-3
-</pre>
-<p>The reason is that Python does LATE binding <em>always</em>. The solution is ugly:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; it = list(lambda i=i:i for i in (1,2,3))
-&gt;&gt;&gt; it[0]()
-1
-&gt;&gt;&gt; it[1]()
-2
-&gt;&gt;&gt; it[2]()
-3
-</pre>
-</div>
-</div>
-<div class="section" id="part-ii-generators">
-<h2><a class="toc-backref" href="#id9" name="part-ii-generators">Part II: generators</a></h2>
-<p>Trivial example:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; def gen123(): # &quot;function&quot; which returns an iterator over the values 1, 2, 3
-... yield 1
-... yield 2
-... yield 3
-...
-&gt;&gt;&gt; it = gen123()
-&gt;&gt;&gt; it.next()
-1
-&gt;&gt;&gt; it.next()
-2
-&gt;&gt;&gt; it.next()
-3
-&gt;&gt;&gt; it.next()
-Traceback (most recent call last):
- ...
-StopIteration
-</pre>
-<p>Real life example: using generators to generate HTML tables</p>
-<pre class="literal-block">
-#&lt;htmltable.py&gt;
-
-def HTMLTablegen(table):
- yield &quot;&lt;table&gt;&quot;
- for row in table:
- yield &quot;&lt;tr&gt;&quot;
- for col in row:
- yield &quot;&lt;td&gt;%s&lt;/td&gt;&quot; % col
- yield &quot;&lt;/tr&gt;&quot;
- yield &quot;&lt;/table&gt;&quot;
-
-def test():
- return &quot;\n&quot;.join(HTMLTablegen([[&quot;Row&quot;, &quot;City&quot;],
- [1,'London'], [2, 'Oxford']]))
-
-if __name__ == &quot;__main__&quot;: # example
- print test()
-
-#&lt;/htmltable.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from htmltable import test
-&gt;&gt;&gt; print test()
-&lt;table&gt;
-&lt;tr&gt;
-&lt;td&gt;Row&lt;/td&gt;
-&lt;td&gt;City&lt;/td&gt;
-&lt;/tr&gt;
-&lt;tr&gt;
-&lt;td&gt;1&lt;/td&gt;
-&lt;td&gt;London&lt;/td&gt;
-&lt;/tr&gt;
-&lt;tr&gt;
-&lt;td&gt;2&lt;/td&gt;
-&lt;td&gt;Oxford&lt;/td&gt;
-&lt;/tr&gt;
-&lt;/table&gt;
-</pre>
-<div class="section" id="a-simple-recipe-skip-redundant">
-<h3><a class="toc-backref" href="#id10" name="a-simple-recipe-skip-redundant">A simple recipe: skip redundant</a></h3>
-<p>How to remove duplicates by keeping the order:</p>
-<pre class="literal-block">
-#&lt;skip_redundant.py&gt;
-
-def skip_redundant(iterable, skipset=None):
- &quot;Redundant items are repeated items or items in the original skipset.&quot;
- if skipset is None: skipset = set()
- for item in iterable:
- if item not in skipset:
- skipset.add(item)
- yield item
-
-#&lt;/skip_redundant.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from skip_redundant import skip_redundant
-&gt;&gt;&gt; print list(skip_redundant(&quot;&lt;hello, world&gt;&quot;, skipset=set(&quot;&lt;&gt;&quot;)))
-['h', 'e', 'l', 'o', ',', ' ', 'w', 'r', 'd']
-</pre>
-</div>
-<div class="section" id="another-real-life-example-working-with-nested-structures">
-<h3><a class="toc-backref" href="#id11" name="another-real-life-example-working-with-nested-structures">Another real life example: working with nested structures</a></h3>
-<pre class="literal-block">
-#&lt;walk.py&gt;
-
-def walk(iterable, level=0):
- for obj in iterable:
- if not hasattr(obj, &quot;__iter__&quot;): # atomic object
- yield obj, level
- else: # composed object: iterate again
- for subobj, lvl in walk(obj, level + 1):
- yield subobj, lvl
-
-def flatten(iterable):
- return (obj for obj, level in walk(iterable))
-
-def pprint(iterable):
- for obj, level in walk(iterable):
- print &quot; &quot;*level, obj
-
-#&lt;/walk.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from walk import flatten, pprint
-&gt;&gt;&gt; nested_ls = [1,[2,[3,[[[4,5],6]]]],7]
-&gt;&gt;&gt; pprint(nested_ls)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
-&gt;&gt;&gt; pprint(flatten(nested_ls))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
-</pre>
-</div>
-<div class="section" id="another-typical-use-case-for-generators-parsers">
-<h3><a class="toc-backref" href="#id12" name="another-typical-use-case-for-generators-parsers">Another typical use case for generators: parsers</a></h3>
-<p>A very stripped down parser for nested expressions</p>
-<pre class="literal-block">
-#&lt;sexpr2indent.py&gt;
-&quot;&quot;&quot;A simple s-expression formatter.&quot;&quot;&quot;
-
-import re
-
-def parse(sexpr):
- position = 0
- nesting_level = 0
- paren = re.compile(r&quot;(?P&lt;paren_beg&gt;\()|(?P&lt;paren_end&gt;\))&quot;)
- while True:
- match = paren.search(sexpr, position)
- if match:
- yield nesting_level, sexpr[position: match.start()]
- if match.lastgroup == &quot;paren_beg&quot;:
- nesting_level += 1
- elif match.lastgroup == &quot;paren_end&quot;:
- nesting_level -= 1
- position = match.end()
- else:
- break
-
-def sexpr_indent(sexpr):
- for nesting, text in parse(sexpr.replace(&quot;\n&quot;, &quot;&quot;)):
- if text.strip(): print &quot; &quot;*nesting, text
-
-#&lt;/sexpr2indent.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from sexpr2indent import sexpr_indent
-&gt;&gt;&gt; sexpr_indent(&quot;&quot;&quot;\
-... (html (head (title Example)) (body (h1 s-expr formatter example)
-... (a (&#64; (href http://www.example.com)) A link)))&quot;&quot;&quot;)
-... #doctest: +NORMALIZE_WHITESPACE
- html
- head
- title Example
- body
- h1 s-expr formatter example
- a
- &#64;
- href http://www.example.com
- A link
-</pre>
-</div>
-<div class="section" id="other-kinds-of-iterables">
-<h3><a class="toc-backref" href="#id13" name="other-kinds-of-iterables">Other kinds of iterables</a></h3>
-<p>The following class generates iterable which are not iterators:</p>
-<pre class="literal-block">
-#&lt;reiterable.py&gt;
-
-class ReIter(object):
- &quot;A re-iterable object.&quot;
- def __iter__(self):
- yield 1
- yield 2
- yield 3
-
-#&lt;/reiterable.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from reiterable import ReIter
-&gt;&gt;&gt; rit = ReIter()
-&gt;&gt;&gt; list(rit)
-[1, 2, 3]
-&gt;&gt;&gt; list(rit) # it is reiterable!
-[1, 2, 3]
-</pre>
-</div>
-<div class="section" id="the-itertools-module">
-<h3><a class="toc-backref" href="#id14" name="the-itertools-module">The itertools module</a></h3>
-<blockquote>
-<ul class="simple">
-<li>count([n]) --&gt; n, n+1, n+2, ...</li>
-<li>cycle(p) --&gt; p0, p1, ... plast, p0, p1, ...</li>
-<li>repeat(elem [,n]) --&gt; elem, elem, elem, ... endlessly or up to n times</li>
-<li>izip(p, q, ...) --&gt; (p[0], q[0]), (p[1], q[1]), ...</li>
-<li>ifilter(pred, seq) --&gt; elements of seq where pred(elem) is True</li>
-<li>ifilterfalse(pred, seq) --&gt; elements of seq where pred(elem) is False</li>
-<li>islice(seq, [start,] stop [, step]) --&gt; elements from seq[start:stop:step]</li>
-<li>imap(fun, p, q, ...) --&gt; fun(p0, q0), fun(p1, q1), ...</li>
-<li>starmap(fun, seq) --&gt; fun(*seq[0]), fun(*seq[1]), ...</li>
-<li>tee(it, n=2) --&gt; (it1, it2 , ... itn) splits one iterator into n</li>
-<li>chain(p, q, ...) --&gt; p0, p1, ... plast, q0, q1, ...</li>
-<li>takewhile(pred, seq) --&gt; seq[0], seq[1], until pred fails</li>
-<li>dropwhile(pred, seq) --&gt; seq[n], seq[n+1], starting when pred fails</li>
-<li>groupby(iterable[, keyfunc]) --&gt; sub-iterators grouped by value of keyfunc(v)</li>
-</ul>
-</blockquote>
-</div>
-<div class="section" id="anytrue">
-<h3><a class="toc-backref" href="#id15" name="anytrue">anyTrue</a></h3>
-<pre class="doctest-block">
-&gt;&gt;&gt; import itertools
-&gt;&gt;&gt; def anyTrue(predicate, iterable):
-... return True in itertools.imap(predicate, iterable)
-...
-&gt;&gt;&gt; fname = &quot;picture.gif&quot;
-&gt;&gt;&gt; anyTrue(fname.endswith, &quot;.jpg .gif .png&quot;.split())
-True
-</pre>
-<p>AnyTrue does <em>short-circuit</em>:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; def is3(i):
-... print &quot;i=%s&quot; % i
-... return i == 3
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; anyTrue(is3, range(10))
-i=0
-i=1
-i=2
-i=3
-True
-</pre>
-</div>
-<div class="section" id="chop">
-<h3><a class="toc-backref" href="#id16" name="chop">chop</a></h3>
-<p>You want to chop an iterable in batches of a given size:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; from chop import chop
-&gt;&gt;&gt; list(chop([1, 2, 3, 4], 2))
-[[1, 2], [3, 4]]
-&gt;&gt;&gt; list(chop([1, 2, 3, 4, 5, 6, 7],3))
-[[1, 2, 3], [4, 5, 6], [7]]
-</pre>
-<p>Here is a possible implementation:</p>
-<pre class="literal-block">
-#&lt;chop.py&gt;
-
-# see also http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/303279
-
-import itertools
-
-def chop(iterable, batchsize):
- it = iter(iterable)
- while True:
- batch = list(itertools.islice(it, batchsize))
- if batch: yield batch
- else: break
-
-#&lt;/chop.py&gt;
-</pre>
-<p>For people thinking Python is too readable, here is a one-liner:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; chop = lambda it, n : itertools.izip(*(iter(it),)*n)
-...
-&gt;&gt;&gt; list(chop([1,2,3,4], 2))
-[(1, 2), (3, 4)]
-</pre>
-</div>
-<div class="section" id="tee">
-<h3><a class="toc-backref" href="#id17" name="tee">tee</a></h3>
-<p>To make copies of iterables; typically used in parsers:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; from itertools import tee, chain, izip
-&gt;&gt;&gt; chars, prevs = tee(&quot;abc&quot;)
-&gt;&gt;&gt; prevs = chain([None], prevs)
-&gt;&gt;&gt; for char, prev in izip(chars, prevs):
-... print char, prev
-...
-a None
-b a
-c b
-</pre>
-</div>
-<div class="section" id="grouping-and-sorting">
-<h3><a class="toc-backref" href="#id18" name="grouping-and-sorting">Grouping and sorting</a></h3>
-<pre class="doctest-block">
-&gt;&gt;&gt; from itertools import groupby
-&gt;&gt;&gt; from operator import itemgetter
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; NAME, AGE = 0, 1
-&gt;&gt;&gt; query_result = (&quot;Smith&quot;, 34), (&quot;Donaldson&quot;, 34), (&quot;Lee&quot;, 22), (&quot;Orr&quot;, 22)
-</pre>
-<p>Grouping together people of the same age:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; for k, g in groupby(query_result, key=itemgetter(AGE)):
-... print k, list(g)
-...
-34 [('Smith', 34), ('Donaldson', 34)]
-22 [('Lee', 22), ('Orr', 22)]
-</pre>
-<p>Sorting by name:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; for tup in sorted(query_result, key=itemgetter(NAME)):
-... print tup
-('Donaldson', 34)
-('Lee', 22)
-('Orr', 22)
-('Smith', 34)
-</pre>
-</div>
-</div>
-</div>
-<div class="section" id="lecture-2-objects-delegation-inheritance">
-<h1><a class="toc-backref" href="#id19" name="lecture-2-objects-delegation-inheritance">Lecture 2: Objects (delegation &amp; inheritance)</a></h1>
-<div class="section" id="part-i-delegation">
-<h2><a class="toc-backref" href="#id20" name="part-i-delegation">Part I: delegation</a></h2>
-<p>Understanding how attribute access works: internal delegation via <em>descriptors</em></p>
-<div class="section" id="accessing-simple-attributes">
-<h3><a class="toc-backref" href="#id21" name="accessing-simple-attributes">Accessing simple attributes</a></h3>
-<pre class="doctest-block">
-&gt;&gt;&gt; class C(object):
-... a = 2
-... def __init__(self, x):
-... self.x = x
-...
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; c = C(1)
-&gt;&gt;&gt; c.x
-1
-&gt;&gt;&gt; c.a
-2
-</pre>
-<p>We are retrieving</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; c.__dict__[&quot;x&quot;]
-1
-</pre>
-<p>If there is nothing in c.__dict__, Python looks at C.__dict__:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; print c.__dict__.get(&quot;a&quot;)
-None
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; C.__dict__[&quot;a&quot;]
-2
-</pre>
-<p>If there is nothing in C.__dict__, Python looks at the superclasses according
-to the MRO (see part II).</p>
-</div>
-<div class="section" id="accessing-methods">
-<h3><a class="toc-backref" href="#id22" name="accessing-methods">Accessing methods</a></h3>
-<pre class="doctest-block">
-&gt;&gt;&gt; c.__init__ #doctest: +ELLIPSIS
-&lt;bound method C.__init__ of &lt;__main__.C object at 0x...&gt;&gt;
-</pre>
-<p>since __init__ is not in c.__dict__ Python looks in the class dictionary
-and finds</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; C.__dict__[&quot;__init__&quot;] #doctest: +ELLIPSIS
-&lt;function __init__ at 0x...&gt;
-</pre>
-<p>Then it magically converts the function into a method bound to the instance
-&quot;c&quot;.</p>
-<p>NOTE: this mechanism works for new-style classes only.</p>
-<p>The old-style mechanism is less consistent and the attribute lookup of special
-methods is special: (*)</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; class C(object): pass
-&gt;&gt;&gt; c = C()
-&gt;&gt;&gt; c.__str__ = lambda : &quot;hello!&quot;
-&gt;&gt;&gt; print c #doctest: +ELLIPSIS
-&lt;__main__.C object at ...&gt;
-</pre>
-<p>whereas for old-style classes</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; class C: pass
-&gt;&gt;&gt; c = C()
-&gt;&gt;&gt; c.__str__ = lambda : &quot;hello!&quot;
-&gt;&gt;&gt; print c
-hello!
-</pre>
-<p>the special method is looked for in the instance dictionary too.</p>
-<p>(*) modulo a very subtle difference for __getattr__-delegated special methods,
-see later.</p>
-</div>
-<div class="section" id="converting-functions-into-methods">
-<h3><a class="toc-backref" href="#id23" name="converting-functions-into-methods">Converting functions into methods</a></h3>
-<p>It is possible to convert a function into a bound or unbound method
-by invoking the <tt class="docutils literal"><span class="pre">__get__</span></tt> special method:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; def f(x): pass
-&gt;&gt;&gt; f.__get__ #doctest: +ELLIPSIS
-&lt;method-wrapper object at 0x...&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; class C(object): pass
-...
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; def f(self): pass
-...
-&gt;&gt;&gt; f.__get__(C(), C) #doctest: +ELLIPSIS
-&lt;bound method C.f of &lt;__main__.C object at 0x...&gt;&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; f.__get__(None, C)
-&lt;unbound method C.f&gt;
-</pre>
-<p>Functions are the simplest example of <em>descriptors</em>.</p>
-<p>Access to methods works since internally Python transforms</p>
-<blockquote>
-<tt class="docutils literal"><span class="pre">c.__init__</span> <span class="pre">-&gt;</span> <span class="pre">type(c).__dict__['__init__'].__get__(c,</span> <span class="pre">type(c))</span></tt></blockquote>
-<p>Note: not <em>all</em> functions are descriptors:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; from operator import add
-&gt;&gt;&gt; add.__get__
-Traceback (most recent call last):
- ...
-AttributeError: 'builtin_function_or_method' object has no attribute '__get__'
-</pre>
-</div>
-<div class="section" id="hack-a-very-slick-adder">
-<h3><a class="toc-backref" href="#id24" name="hack-a-very-slick-adder">Hack: a very slick adder</a></h3>
-<p>The descriptor protocol can be (ab)used as a way to avoid the late binding
-issue in for loops:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; def add(x,y):
-... return x + y
-&gt;&gt;&gt; closures = [add.__get__(i) for i in range(10)]
-&gt;&gt;&gt; closures[5](1000)
-1005
-</pre>
-<p>Notice: operator.add will not work.</p>
-</div>
-<div class="section" id="descriptor-protocol">
-<h3><a class="toc-backref" href="#id25" name="descriptor-protocol">Descriptor Protocol</a></h3>
-<p>Everything at <a class="reference" href="http://users.rcn.com/python/download/Descriptor.htm">http://users.rcn.com/python/download/Descriptor.htm</a></p>
-<p>Formally:</p>
-<pre class="literal-block">
-descr.__get__(self, obj, type=None) --&gt; value
-descr.__set__(self, obj, value) --&gt; None
-descr.__delete__(self, obj) --&gt; None
-</pre>
-<p>Examples of custom descriptors:</p>
-<pre class="literal-block">
-#&lt;descriptor.py&gt;
-
-
-class AttributeDescriptor(object):
- def __get__(self, obj, cls=None):
- if obj is None and cls is None:
- raise TypeError(&quot;__get__(None, None) is invalid&quot;)
- elif obj is None:
- return self.get_from_class(cls)
- else:
- return self.get_from_obj(obj)
- def get_from_class(self, cls):
- print &quot;Getting %s from %s&quot; % (self, cls)
- def get_from_obj(self, obj):
- print &quot;Getting %s from %s&quot; % (self, obj)
-
-
-class Staticmethod(AttributeDescriptor):
- def __init__(self, func):
- self.func = func
- def get_from_class(self, cls):
- return self.func
- get_from_obj = get_from_class
-
-
-class Classmethod(AttributeDescriptor):
- def __init__(self, func):
- self.func = func
- def get_from_class(self, cls):
- return self.func.__get__(cls, type(cls))
- def get_from_obj(self, obj):
- return self.get_from_class(obj.__class__)
-
-class C(object):
- s = Staticmethod(lambda : 1)
- c = Classmethod(lambda cls : cls.__name__)
-
-c = C()
-
-assert C.s() == c.s() == 1
-assert C.c() == c.c() == &quot;C&quot;
-
-#&lt;/descriptor.py&gt;
-</pre>
-</div>
-<div class="section" id="multilingual-attribute">
-<h3><a class="toc-backref" href="#id26" name="multilingual-attribute">Multilingual attribute</a></h3>
-<p>Inspirated by a question in the Italian Newsgroup:</p>
-<pre class="literal-block">
-#&lt;multilingual.py&gt;
-
-import sys
-from descriptor import AttributeDescriptor
-
-class MultilingualAttribute(AttributeDescriptor):
- &quot;&quot;&quot;When a MultilingualAttribute is accessed, you get the translation
- corresponding to the currently selected language.
- &quot;&quot;&quot;
- def __init__(self, **translations):
- self.trans = translations
- def get_from_class(self, cls):
- return self.trans[getattr(cls, &quot;language&quot;, None) or
- sys.modules[cls.__module__].language]
- def get_from_obj(self, obj):
- return self.trans[getattr(obj, &quot;language&quot;, None) or
- sys.modules[obj.__class__.__module__].language]
-
-
-language = &quot;en&quot;
-
-# a dummy User class
-class DefaultUser(object):
- def has_permission(self):
- return False
-
-class WebApplication(object):
- error_msg = MultilingualAttribute(
- en=&quot;You cannot access this page&quot;,
- it=&quot;Questa pagina non e' accessibile&quot;,
- fr=&quot;Vous ne pouvez pas acceder cette page&quot;,)
- user = DefaultUser()
- def __init__(self, language=None):
- self.language = language or getattr(self.__class__, &quot;language&quot;, None)
- def show_page(self):
- if not self.user.has_permission():
- return self.error_msg
-
-
-app = WebApplication()
-assert app.show_page() == &quot;You cannot access this page&quot;
-
-app.language = &quot;fr&quot;
-assert app.show_page() == &quot;Vous ne pouvez pas acceder cette page&quot;
-
-app.language = &quot;it&quot;
-assert app.show_page() == &quot;Questa pagina non e' accessibile&quot;
-
-app.language = &quot;en&quot;
-assert app.show_page() == &quot;You cannot access this page&quot;
-
-#&lt;/multilingual.py&gt;
-</pre>
-<p>The same can be done with properties:</p>
-<pre class="literal-block">
-#&lt;multilingualprop.py&gt;
-
-language = &quot;en&quot;
-
-# a dummy User class
-class DefaultUser(object):
- def has_permission(self):
- return False
-
-def multilingualProperty(**trans):
- def get(self):
- return trans[self.language]
- def set(self, value):
- trans[self.language] = value
- return property(get, set)
-
-class WebApplication(object):
- language = language
- error_msg = multilingualProperty(
- en=&quot;You cannot access this page&quot;,
- it=&quot;Questa pagina non e' accessibile&quot;,
- fr=&quot;Vous ne pouvez pas acceder cette page&quot;,)
- user = DefaultUser()
- def __init__(self, language=None):
- if language: self.language = self.language
- def show_page(self):
- if not self.user.has_permission():
- return self.error_msg
-
-#&lt;/multilingualprop.py&gt;
-</pre>
-<p>This also gives the possibility to set the error messages.</p>
-<p>The difference with the descriptor approach</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; from multilingual import WebApplication
-&gt;&gt;&gt; app = WebApplication()
-&gt;&gt;&gt; print app.error_msg
-You cannot access this page
-&gt;&gt;&gt; print WebApplication.error_msg
-You cannot access this page
-</pre>
-<p>is that with properties there is no nice access from the class:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; from multilingualprop import WebApplication
-&gt;&gt;&gt; WebApplication.error_msg #doctest: +ELLIPSIS
-&lt;property object at ...&gt;
-</pre>
-</div>
-<div class="section" id="another-use-case-for-properties-storing-users">
-<h3><a class="toc-backref" href="#id27" name="another-use-case-for-properties-storing-users">Another use case for properties: storing users</a></h3>
-<p>Consider a library providing a simple User class:</p>
-<pre class="literal-block">
-#&lt;crypt_user.py&gt;
-
-class User(object):
- def __init__(self, username, password):
- self.username, self.password = username, password
-
-#&lt;/crypt_user.py&gt;
-</pre>
-<p>The User objects are stored in a database as they are.
-For security purpose, in a second version of the library it is
-decided to crypt the password, so that only crypted passwords
-are stored in the database. With properties, it is possible to
-implement this functionality without changing the source code for
-the User class:</p>
-<pre class="literal-block">
-#&lt;crypt_user.py&gt;
-
-from crypt import crypt
-
-def cryptedAttribute(seed=&quot;x&quot;):
- def get(self):
- return getattr(self, &quot;_pw&quot;, None)
- def set(self, value):
- self._pw = crypt(value, seed)
- return property(get, set)
-
-User.password = cryptedAttribute()
-</pre>
-<p>#&lt;/crypt_user.py&gt;</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; from crypt_user import User
-&gt;&gt;&gt; u = User(&quot;michele&quot;, &quot;secret&quot;)
-&gt;&gt;&gt; print u.password
-xxZREZpkHZpkI
-</pre>
-<p>Notice the property factory approach used here.</p>
-</div>
-<div class="section" id="low-level-delegation-via-getattribute">
-<h3><a class="toc-backref" href="#id28" name="low-level-delegation-via-getattribute">Low-level delegation via __getattribute__</a></h3>
-<p>Attribute access is managed by the__getattribute__ special method:</p>
-<pre class="literal-block">
-#&lt;tracedaccess.py&gt;
-
-class TracedAccess(object):
- def __getattribute__(self, name):
- print &quot;Accessing %s&quot; % name
- return object.__getattribute__(self, name)
-
-
-class C(TracedAccess):
- s = staticmethod(lambda : 'staticmethod')
- c = classmethod(lambda cls: 'classmethod')
- m = lambda self: 'method'
- a = &quot;hello&quot;
-
-#&lt;/tracedaccess.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from tracedaccess import C
-&gt;&gt;&gt; c = C()
-&gt;&gt;&gt; print c.s()
-Accessing s
-staticmethod
-&gt;&gt;&gt; print c.c()
-Accessing c
-classmethod
-&gt;&gt;&gt; print c.m()
-Accessing m
-method
-&gt;&gt;&gt; print c.a
-Accessing a
-hello
-&gt;&gt;&gt; print c.__init__ #doctest: +ELLIPSIS
-Accessing __init__
-&lt;method-wrapper object at 0x...&gt;
-&gt;&gt;&gt; try: c.x
-... except AttributeError, e: print e
-...
-Accessing x
-'C' object has no attribute 'x'
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; c.y = 'y'
-&gt;&gt;&gt; c.y
-Accessing y
-'y'
-</pre>
-<p>You are probably familiar with <tt class="docutils literal"><span class="pre">__getattr__</span></tt> which is similar
-to <tt class="docutils literal"><span class="pre">__getattribute__</span></tt>, but it is called <em>only for missing attributes</em>.</p>
-</div>
-<div class="section" id="traditional-delegation-via-getattr">
-<h3><a class="toc-backref" href="#id29" name="traditional-delegation-via-getattr">Traditional delegation via __getattr__</a></h3>
-<p>Realistic use case in &quot;object publishing&quot;:</p>
-<pre class="literal-block">
-#&lt;webapp.py&gt;
-
-class WebApplication(object):
- def __getattr__(self, name):
- return name.capitalize()
-
-
-app = WebApplication()
-
-assert app.page1 == 'Page1'
-assert app.page2 == 'Page2'
-
-#&lt;/webapp.py&gt;
-</pre>
-<p>Here is another use case in HTML generation:</p>
-<pre class="literal-block">
-#&lt;XMLtag.py&gt;
-
-def makeattr(dict_or_list_of_pairs):
- dic = dict(dict_or_list_of_pairs)
- return &quot; &quot;.join('%s=&quot;%s&quot;' % (k, dic[k]) for k in dic) # simplistic
-
-class XMLTag(object):
- def __getattr__(self, name):
- def tag(value, **attr):
- &quot;&quot;&quot;value can be a string or a sequence of strings.&quot;&quot;&quot;
- if hasattr(value, &quot;__iter__&quot;): # is iterable
- value = &quot; &quot;.join(value)
- return &quot;&lt;%s %s&gt;%s&lt;/%s&gt;&quot; % (name, makeattr(attr), value, name)
- return tag
-
-class XMLShortTag(object):
- def __getattr__(self, name):
- def tag(**attr):
- return &quot;&lt;%s %s /&gt;&quot; % (name, makeattr(attr))
- return tag
-
-tag = XMLTag()
-tg = XMLShortTag()
-
-#&lt;/XMLtag.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from XMLtag import tag, tg
-&gt;&gt;&gt; print tag.a(&quot;example.com&quot;, href=&quot;http://www.example.com&quot;)
-&lt;a href=&quot;http://www.example.com&quot;&gt;example.com&lt;/a&gt;
-&gt;&gt;&gt; print tg.br(**{'class':&quot;br_style&quot;})
-&lt;br class=&quot;br_style&quot; /&gt;
-</pre>
-</div>
-<div class="section" id="keyword-dictionaries-with-getattr-setattr">
-<h3><a class="toc-backref" href="#id30" name="keyword-dictionaries-with-getattr-setattr">Keyword dictionaries with __getattr__/__setattr__</a></h3>
-<pre class="literal-block">
-#&lt;kwdict.py&gt;
-
-class kwdict(dict): # or UserDict, to make it to work with Zope
- &quot;&quot;&quot;A typing shortcut used in place of a keyword dictionary.&quot;&quot;&quot;
- def __getattr__(self, name):
- return self[name]
- def __setattr__(self, name, value):
- self[name] = value
-
-#&lt;/kwdict.py&gt;
-</pre>
-<p>And now for a completely different solution:</p>
-<pre class="literal-block">
-#&lt;dictwrapper.py&gt;
-
-class DictWrapper(object):
- def __init__(self, **kw):
- self.__dict__.update(kw)
-
-#&lt;/dictwrapper.py&gt;
-</pre>
-</div>
-<div class="section" id="delegation-to-special-methods-caveat">
-<h3><a class="toc-backref" href="#id31" name="delegation-to-special-methods-caveat">Delegation to special methods caveat</a></h3>
-<pre class="doctest-block">
-&gt;&gt;&gt; class ListWrapper(object):
-... def __init__(self, ls):
-... self._list = ls
-... def __getattr__(self, name):
-... if name == &quot;__getitem__&quot;: # special method
-... return self._list.__getitem__
-... elif name == &quot;reverse&quot;: # regular method
-... return self._list.reverse
-... else:
-... raise AttributeError(&quot;%r is not defined&quot; % name)
-...
-&gt;&gt;&gt; lw = ListWrapper([0,1,2])
-&gt;&gt;&gt; print lw.x
-Traceback (most recent call last):
- ...
-AttributeError: 'x' is not defined
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; lw.reverse()
-&gt;&gt;&gt; print lw.__getitem__(0)
-2
-&gt;&gt;&gt; print lw.__getitem__(1)
-1
-&gt;&gt;&gt; print lw.__getitem__(2)
-0
-&gt;&gt;&gt; print lw[0]
-Traceback (most recent call last):
- ...
-TypeError: unindexable object
-</pre>
-</div>
-</div>
-<div class="section" id="part-ii-inheritance">
-<h2><a class="toc-backref" href="#id32" name="part-ii-inheritance">Part II: Inheritance</a></h2>
-<p>The major changes in inheritance from Python 2.1 to 2.2+ are:</p>
-<ol class="arabic simple">
-<li>you can subclass built-in types (as a consequence the constructor__new__
-has been exposed to the user, to help subclassing immutable types);</li>
-<li>the Method Resolution Order (MRO) has changed;</li>
-<li>now Python allows <em>cooperative method calls</em>, i.e. we have <em>super</em>.</li>
-</ol>
-<div class="section" id="why-you-need-to-know-about-mi-even-if-you-do-not-use-it">
-<h3><a class="toc-backref" href="#id33" name="why-you-need-to-know-about-mi-even-if-you-do-not-use-it">Why you need to know about MI even if you do not use it</a></h3>
-<p>In principle, the last two changes are relevant only if you use multiple
-inheritance. If you use single inheritance only, you don't need <tt class="docutils literal"><span class="pre">super</span></tt>:
-you can just name the superclass.
-However, somebody else may want to use your class in a MI hierarchy,
-and you would make her life difficult if you don't use <tt class="docutils literal"><span class="pre">super</span></tt>.</p>
-<p>My SI hierarchy:</p>
-<pre class="literal-block">
-#&lt;why_super.py&gt;
-
-class Base(object):
- def __init__(self):
- print &quot;B.__init__&quot;
-
-class MyClass(Base):
- &quot;I do not cooperate with others&quot;
- def __init__(self):
- print &quot;MyClass.__init__&quot;
- Base.__init__(self) #instead of super(MyClass, self).__init__()
-
-#&lt;/why_super.py&gt;
-</pre>
-<p>Her MI hierarchy:</p>
-<pre class="literal-block">
-#&lt;why_super.py&gt;
-
-class Mixin(Base):
- &quot;I am cooperative with others&quot;
- def __init__(self):
- print &quot;Mixin.__init__&quot;
- super(Mixin, self).__init__()
-
-class HerClass(MyClass, Mixin):
- &quot;I am supposed to be cooperative too&quot;
- def __init__(self):
- print &quot;HerClass.__init__&quot;
- super(HerClass, self).__init__()
-
-#&lt;/why_super.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from why_super import HerClass
-&gt;&gt;&gt; h = HerClass() # Mixin.__init__ is not called!
-HerClass.__init__
-MyClass.__init__
-B.__init__
-</pre>
-<blockquote>
-<pre class="literal-block">
- 4 object
- |
- 3 Base
- / \
-1 MyClass 2 Mixin
- \ /
- 0 HerClass
-</pre>
-</blockquote>
-<pre class="doctest-block">
-&gt;&gt;&gt; [ancestor.__name__ for ancestor in HerClass.mro()]
-['HerClass', 'MyClass', 'Mixin', 'Base', 'object']
-</pre>
-<p>In order to be polite versus your future users, you should use <tt class="docutils literal"><span class="pre">super</span></tt>
-always. This adds a cognitive burden even for people not using MI :-(</p>
-<p>Notice that there is no good comprehensive reference on <tt class="docutils literal"><span class="pre">super</span></tt> (yet)
-Your best bet is still <a class="reference" href="http://www.python.org/2.2.3/descrintro.html#cooperation">http://www.python.org/2.2.3/descrintro.html#cooperation</a></p>
-<p>The MRO instead is explained here: <a class="reference" href="http://www.python.org/2.3/mro.html">http://www.python.org/2.3/mro.html</a></p>
-<p>Notice that I DO NOT recommand Multiple Inheritance.</p>
-<p>More often than not you are better off using composition/delegation/wrapping,
-etc.</p>
-<p>See Zope 2 -&gt; Zope 3 experience.</p>
-</div>
-<div class="section" id="a-few-details-about-super-not-the-whole-truth">
-<h3><a class="toc-backref" href="#id34" name="a-few-details-about-super-not-the-whole-truth">A few details about <tt class="docutils literal docutils literal"><span class="pre">super</span></tt> (not the whole truth)</a></h3>
-<pre class="doctest-block">
-&gt;&gt;&gt; class B(object):
-... def __init__(self): print &quot;B.__init__&quot;
-...
-&gt;&gt;&gt; class C(B):
-... def __init__(self): print &quot;C.__init__&quot;
-...
-&gt;&gt;&gt; c = C()
-C.__init__
-</pre>
-<p><tt class="docutils literal"><span class="pre">super(cls,</span> <span class="pre">instance)</span></tt>, where <tt class="docutils literal"><span class="pre">instance</span></tt> is an instance of <tt class="docutils literal"><span class="pre">cls</span></tt> or of
-a subclass of <tt class="docutils literal"><span class="pre">cls</span></tt>, retrieves the right method in the MRO:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; super(C, c).__init__ #doctest: +ELLIPSIS
-&lt;bound method C.__init__ of &lt;__main__.C object at 0x...&gt;&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; super(C, c).__init__.im_func is B.__init__.im_func
-True
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; super(C, c).__init__()
-B.__init__
-</pre>
-<p><tt class="docutils literal"><span class="pre">super(cls,</span> <span class="pre">subclass)</span></tt> works for unbound methods:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; super(C, C).__init__
-&lt;unbound method C.__init__&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; super(C, C).__init__.im_func is B.__init__.im_func
-True
-&gt;&gt;&gt; super(C, C).__init__(c)
-B.__init__
-</pre>
-<p><tt class="docutils literal"><span class="pre">super(cls,</span> <span class="pre">subclass)</span></tt> is also necessary for classmethods and staticmethods.
-Properties and custom descriptorsw works too:</p>
-<pre class="literal-block">
-#&lt;super_ex.py&gt;
-
-from descriptor import AttributeDescriptor
-
-class B(object):
- &#64;staticmethod
- def sm(): return &quot;staticmethod&quot;
-
- &#64;classmethod
- def cm(cls): return cls.__name__
-
- p = property()
- a = AttributeDescriptor()
-
-class C(B): pass
-
-#&lt;/super_ex.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from super_ex import C
-</pre>
-<p>Staticmethod usage:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; super(C, C).sm #doctest: +ELLIPSIS
-&lt;function sm at 0x...&gt;
-&gt;&gt;&gt; super(C, C).sm()
-'staticmethod'
-</pre>
-<p>Classmethod usage:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; super(C, C()).cm
-&lt;bound method type.cm of &lt;class 'super_ex.C'&gt;&gt;
-&gt;&gt;&gt; super(C, C).cm() # C is automatically passed
-'C'
-</pre>
-<p>Property usage:</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; print super(C, C).p #doctest: +ELLIPSIS
-&lt;property object at 0x...&gt;
-&gt;&gt;&gt; super(C, C).a #doctest: +ELLIPSIS
-Getting &lt;descriptor.AttributeDescriptor object at 0x...&gt; from &lt;class 'super_ex.C'&gt;
-</pre>
-<p><tt class="docutils literal"><span class="pre">super</span></tt> does not work with old-style classes, however you can use the
-following trick:</p>
-<pre class="literal-block">
-#&lt;super_old_new.py&gt;
-class O:
- def __init__(self):
- print &quot;O.__init__&quot;
-
-class N(O, object):
- def __init__(self):
- print &quot;N.__init__&quot;
- super(N, self).__init__()
-
-#&lt;/super_old_new.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from super_old_new import N
-&gt;&gt;&gt; new = N()
-N.__init__
-O.__init__
-</pre>
-<p>There are dozens of tricky points concerning <tt class="docutils literal"><span class="pre">super</span></tt>, be warned!</p>
-</div>
-<div class="section" id="subclassing-built-in-types-new-vs-init">
-<h3><a class="toc-backref" href="#id35" name="subclassing-built-in-types-new-vs-init">Subclassing built-in types; __new__ vs. __init__</a></h3>
-<pre class="literal-block">
-#&lt;point.py&gt;
-
-class NotWorkingPoint(tuple):
- def __init__(self, x, y):
- super(NotWorkingPoint, self).__init__((x,y))
- self.x, self.y = x, y
-
-#&lt;/point.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from point import NotWorkingPoint
-&gt;&gt;&gt; p = NotWorkingPoint(2,3)
-Traceback (most recent call last):
- ...
-TypeError: tuple() takes at most 1 argument (2 given)
-</pre>
-<pre class="literal-block">
-#&lt;point.py&gt;
-
-class Point(tuple):
- def __new__(cls, x, y):
- return super(Point, cls).__new__(cls, (x,y))
- def __init__(self, x, y):
- super(Point, self).__init__((x, y))
- self.x, self.y = x, y
-
-#&lt;/point.py&gt;
-</pre>
-<p>Notice that__new__ is a staticmethod, not a classmethod, so one needs
-to pass the class explicitely.</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; from point import Point
-&gt;&gt;&gt; p = Point(2,3)
-&gt;&gt;&gt; print p, p.x, p.y
-(2, 3) 2 3
-</pre>
-</div>
-<div class="section" id="be-careful-when-using-new-with-mutable-types">
-<h3><a class="toc-backref" href="#id36" name="be-careful-when-using-new-with-mutable-types">Be careful when using __new__ with mutable types</a></h3>
-<pre class="doctest-block">
-&gt;&gt;&gt; class ListWithDefault(list):
-... def __new__(cls):
-... return super(ListWithDefault, cls).__new__(cls, [&quot;hello&quot;])
-...
-&gt;&gt;&gt; print ListWithDefault() # beware! NOT [&quot;hello&quot;]!
-[]
-</pre>
-<p>Reason: lists are re-initialized to empty lists in list.__init__!</p>
-<p>Instead</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; class ListWithDefault(list):
-... def __init__(self):
-... super(ListWithDefault, self).__init__([&quot;hello&quot;])
-...
-&gt;&gt;&gt; print ListWithDefault() # works!
-['hello']
-</pre>
-</div>
-</div>
-</div>
-<div class="section" id="lecture-3-magic-i-e-decorators-and-metaclasses">
-<h1><a class="toc-backref" href="#id37" name="lecture-3-magic-i-e-decorators-and-metaclasses">Lecture 3: Magic (i.e. decorators and metaclasses)</a></h1>
-<div class="section" id="part-i-decorators">
-<h2><a class="toc-backref" href="#id38" name="part-i-decorators">Part I: decorators</a></h2>
-<p>Decorators are just sugar: their functionality was already in the language</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; def s(): pass
-&gt;&gt;&gt; s = staticmethod(s)
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; &#64;staticmethod
-... def s(): pass
-...
-</pre>
-<p>However sugar <em>does</em> matter.</p>
-<div class="section" id="a-typical-decorator-traced">
-<h3><a class="toc-backref" href="#id39" name="a-typical-decorator-traced">A typical decorator: traced</a></h3>
-<pre class="literal-block">
-#&lt;traced.py&gt;
-
-def traced(func):
- def tracedfunc(*args, **kw):
- print &quot;calling %s.%s&quot; % (func.__module__, func.__name__)
- return func(*args, **kw)
- tracedfunc.__name__ = func.__name__
- return tracedfunc
-
-&#64;traced
-def f(): pass
-
-#&lt;/traced.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from traced import f
-&gt;&gt;&gt; f()
-calling traced.f
-</pre>
-</div>
-<div class="section" id="a-decorator-factory-timed">
-<h3><a class="toc-backref" href="#id40" name="a-decorator-factory-timed">A decorator factory: Timed</a></h3>
-<pre class="literal-block">
-#&lt;timed.py&gt;
-
-import sys, time
-
-class Timed(object):
- &quot;&quot;&quot;Decorator factory: each decorator object wraps a function and
- executes it many times (default 100 times).
- The average time spent in one iteration, expressed in milliseconds,
- is stored in the attributes wrappedfunc.time and wrappedfunc.clocktime,
- and displayed into a log file which defaults to stdout.
- &quot;&quot;&quot;
- def __init__(self, repeat=100, logfile=sys.stdout):
- self.repeat = repeat
- self.logfile = logfile
- def __call__(self, func):
- def wrappedfunc(*args, **kw):
- fullname = &quot;%s.%s ...&quot; % (func.__module__, func.func_name)
- print &gt;&gt; self.logfile, 'Executing %s' % fullname.ljust(30),
- time1 = time.time()
- clocktime1 = time.clock()
- for i in xrange(self.repeat):
- res = func(*args,**kw) # executes func self.repeat times
- time2 = time.time()
- clocktime2 = time.clock()
- wrappedfunc.time = 1000*(time2-time1)/self.repeat
- wrappedfunc.clocktime = 1000*(clocktime2 - clocktime1)/self.repeat
- print &gt;&gt; self.logfile, \
- 'Real time: %s ms;' % self.rounding(wrappedfunc.time),
- print &gt;&gt; self.logfile, \
- 'Clock time: %s ms' % self.rounding(wrappedfunc.clocktime)
- return res
- wrappedfunc.func_name = func.func_name
- wrappedfunc.__module__ = func.__module__
- return wrappedfunc
- &#64;staticmethod
- def rounding(float_):
- &quot;Three digits rounding for small numbers, 1 digit rounding otherwise.&quot;
- if float_ &lt; 10.:
- return &quot;%5.3f&quot; % float_
- else:
- return &quot;%5.1f&quot; % float_
-
-#&lt;/timed.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from timed import Timed
-&gt;&gt;&gt; from random import sample
-&gt;&gt;&gt; example_ls = sample(xrange(1000000), 1000)
-&gt;&gt;&gt; &#64;Timed()
-... def list_sort(ls):
-... ls.sort()
-...
-&gt;&gt;&gt; list_sort(example_ls) #doctest: +ELLIPSIS
-Executing __main__.list_sort ... Real time: 0... ms; Clock time: 0... ms
-</pre>
-</div>
-<div class="section" id="a-powerful-decorator-pattern">
-<h3><a class="toc-backref" href="#id41" name="a-powerful-decorator-pattern">A powerful decorator pattern</a></h3>
-<pre class="literal-block">
-#&lt;traced_function2.py&gt;
-
-from decorators import decorator
-
-def trace(f, *args, **kw):
- print &quot;calling %s with args %s, %s&quot; % (f.func_name, args, kw)
- return f(*args, **kw)
-
-traced_function = decorator(trace)
-
-&#64;traced_function
-def f1(x):
- pass
-
-&#64;traced_function
-def f2(x, y):
- pass
-
-#&lt;/traced_function2.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from traced_function2 import traced_function, f1, f2
-&gt;&gt;&gt; f1(1)
-calling f1 with args (1,), {}
-&gt;&gt;&gt; f2(1,2)
-calling f2 with args (1, 2), {}
-</pre>
-<p>works with pydoc:</p>
-<pre class="literal-block">
-$ pydoc2.4 traced_function2.f2
-Help on function f1 in traced_function2:
-
-traced_function2.f1 = f1(x)
-
-$ pydoc2.4 traced_function2.f2
-Help on function f2 in traced_function2:
-
-traced_function2.f2 = f2(x, y)
-</pre>
-<p>Here is the source code:</p>
-<pre class="literal-block">
-#&lt;decorators.py&gt;
-
-import inspect, itertools
-
-def getinfo(func):
- &quot;&quot;&quot;Return an info dictionary containing:
- - name (the name of the function : str)
- - argnames (the names of the arguments : list)
- - defarg (the values of the default arguments : list)
- - fullsign (the full signature : str)
- - shortsign (the short signature : str)
- - arg0 ... argn (shortcuts for the names of the arguments)
-
- &gt;&gt; def f(self, x=1, y=2, *args, **kw): pass
-
- &gt;&gt; info = getinfo(f)
-
- &gt;&gt; info[&quot;name&quot;]
- 'f'
- &gt;&gt; info[&quot;argnames&quot;]
- ['self', 'x', 'y', 'args', 'kw']
-
- &gt;&gt; info[&quot;defarg&quot;]
- (1, 2)
-
- &gt;&gt; info[&quot;shortsign&quot;]
- 'self, x, y, *args, **kw'
-
- &gt;&gt; info[&quot;fullsign&quot;]
- 'self, x=defarg[0], y=defarg[1], *args, **kw'
-
- &gt;&gt; info[&quot;arg0&quot;], info[&quot;arg1&quot;], info[&quot;arg2&quot;], info[&quot;arg3&quot;], info[&quot;arg4&quot;]
- ('self', 'x', 'y', 'args', 'kw')
- &quot;&quot;&quot;
- assert inspect.ismethod(func) or inspect.isfunction(func)
- regargs, varargs, varkwargs, defaults = inspect.getargspec(func)
- argnames = list(regargs)
- if varargs: argnames.append(varargs)
- if varkwargs: argnames.append(varkwargs)
- counter = itertools.count()
- fullsign = inspect.formatargspec(
- regargs, varargs, varkwargs, defaults,
- formatvalue=lambda value: &quot;=defarg[%i]&quot; % counter.next())[1:-1]
- shortsign = inspect.formatargspec(
- regargs, varargs, varkwargs, defaults,
- formatvalue=lambda value: &quot;&quot;)[1:-1]
- dic = dict((&quot;arg%s&quot; % n, name) for n, name in enumerate(argnames))
- dic.update(name=func.__name__, argnames=argnames, shortsign=shortsign,
- fullsign = fullsign, defarg = func.func_defaults or ())
- return dic
-
-def _contains_reserved_names(dic): # helper
- return &quot;_call_&quot; in dic or &quot;_func_&quot; in dic
-
-def _decorate(func, caller):
- &quot;&quot;&quot;Takes a function and a caller and returns the function
- decorated with that caller. The decorated function is obtained
- by evaluating a lambda function with the correct signature.
- &quot;&quot;&quot;
- infodict = getinfo(func)
- assert not _contains_reserved_names(infodict[&quot;argnames&quot;]), \
- &quot;You cannot use _call_ or _func_ as argument names!&quot;
- execdict=dict(_func_=func, _call_=caller, defarg=func.func_defaults or ())
- if func.__name__ == &quot;&lt;lambda&gt;&quot;:
- lambda_src = &quot;lambda %(fullsign)s: _call_(_func_, %(shortsign)s)&quot; \
- % infodict
- dec_func = eval(lambda_src, execdict)
- else:
- func_src = &quot;&quot;&quot;def %(name)s(%(fullsign)s):
- return _call_(_func_, %(shortsign)s)&quot;&quot;&quot; % infodict
- exec func_src in execdict
- dec_func = execdict[func.__name__]
- dec_func.__doc__ = func.__doc__
- dec_func.__dict__ = func.__dict__
- return dec_func
-
-class decorator(object):
- &quot;&quot;&quot;General purpose decorator factory: takes a caller function as
-input and returns a decorator. A caller function is any function like this::
-
- def caller(func, *args, **kw):
- # do something
- return func(*args, **kw)
-
-Here is an example of usage:
-
- &gt;&gt; &#64;decorator
- .. def chatty(f, *args, **kw):
- .. print &quot;Calling %r&quot; % f.__name__
- .. return f(*args, **kw)
-
- &gt;&gt; &#64;chatty
- .. def f(): pass
- ..
- &gt;&gt; f()
- Calling 'f'
- &quot;&quot;&quot;
- def __init__(self, caller):
- self.caller = caller
- def __call__(self, func):
- return _decorate(func, self.caller)
-
-
-#&lt;/decorators.py&gt;
-</pre>
-<p>The possibilities of this pattern are endless.</p>
-</div>
-<div class="section" id="a-deferred-decorator">
-<h3><a class="toc-backref" href="#id42" name="a-deferred-decorator">A deferred decorator</a></h3>
-<p>You want to execute a procedure only after a certain time delay (for instance
-for use within an asyncronous Web framework):</p>
-<pre class="literal-block">
-#&lt;deferred.py&gt;
-&quot;Deferring the execution of a procedure (function returning None)&quot;
-
-import threading
-from decorators import decorator
-
-def deferred(nsec):
- def call_later(func, *args, **kw):
- return threading.Timer(nsec, func, args, kw).start()
- return decorator(call_later)
-
-&#64;deferred(2)
-def hello():
- print &quot;hello&quot;
-
-if __name__ == &quot;__main__&quot;:
- hello()
- print &quot;Calling hello() ...&quot;
-
-
-#&lt;/deferred.py&gt;
-
-$ python deferred.py
-</pre>
-<p>Show an example of an experimental decorator based web framework
-(doctester_frontend).</p>
-</div>
-</div>
-<div class="section" id="part-ii-metaclasses">
-<h2><a class="toc-backref" href="#id43" name="part-ii-metaclasses">Part II: metaclasses</a></h2>
-<p>Metaclasses are there! Consider this example from a recent post on c.l.py:</p>
-<pre class="literal-block">
-#&lt;BaseClass.py&gt;
-
-class BaseClass(object):
- &quot;Do something&quot;
-
-#&lt;/BaseClass.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; import BaseClass # instead of 'from BaseClass import BaseClass'
-&gt;&gt;&gt; class C(BaseClass): pass
-...
-Traceback (most recent call last):
- ...
-TypeError: Error when calling the metaclass bases
- module.__init__() takes at most 2 arguments (3 given)
-</pre>
-<p>The reason for the error is that class <tt class="docutils literal"><span class="pre">C(BaseClass):</span> <span class="pre">pass</span></tt> is
-actually calling the <tt class="docutils literal"><span class="pre">type</span></tt> metaclass with three arguments:</p>
-<pre class="literal-block">
-C = type(&quot;C&quot;, (BaseClass,), {})
-</pre>
-<p><tt class="docutils literal"><span class="pre">type.__new__</span></tt> tries to use <tt class="docutils literal"><span class="pre">type(BaseClass)</span></tt> as metaclass,
-but since BaseClass here is a module, and <tt class="docutils literal"><span class="pre">ModuleType</span></tt> is not
-a metaclass, it cannot work. The error message reflects a conflict with
-the signature of ModuleType which requires two parameters and not three.</p>
-<p>So even if you don't use them, you may want to know they exist.</p>
-<div class="section" id="rejuvenating-old-style-classes">
-<h3><a class="toc-backref" href="#id44" name="rejuvenating-old-style-classes">Rejuvenating old-style classes</a></h3>
-<pre class="doctest-block">
-&gt;&gt;&gt; class Old: pass
-&gt;&gt;&gt; print type(Old)
-&lt;type 'classobj'&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; __metaclass__ = type # to rejuvenate class
-&gt;&gt;&gt; class NotOld: pass
-...
-&gt;&gt;&gt; print NotOld.__class__
-&lt;type 'type'&gt;
-</pre>
-</div>
-<div class="section" id="a-typical-metaclass-example-metatracer">
-<h3><a class="toc-backref" href="#id45" name="a-typical-metaclass-example-metatracer">A typical metaclass example: MetaTracer</a></h3>
-<pre class="literal-block">
-#&lt;metatracer.py&gt;
-
-import inspect
-from decorators import decorator
-
-&#64;decorator
-def traced(meth, *args, **kw):
- cls = meth.__cls__
- modname = meth.__module__ or cls.__module__
- print &quot;calling %s.%s.%s&quot; % (modname, cls.__name__, meth.__name__)
- return meth(*args, **kw)
-
-class MetaTracer(type):
- def __init__(cls, name, bases, dic):
- super(MetaTracer, cls).__init__(name, bases, dic)
- for k, v in dic.iteritems():
- if inspect.isfunction(v):
- v.__cls__ = cls # so we know in which class v was defined
- setattr(cls, k, traced(v))
-
-#&lt;/metatracer.py&gt;
-</pre>
-<p>Usage: exploring classes in the standard library</p>
-<pre class="literal-block">
-#&lt;dictmixin.py&gt;
-
-from metatracer import MetaTracer
-from UserDict import DictMixin
-
-class TracedDM(DictMixin, object):
- __metaclass__ = MetaTracer
- def __getitem__(self, item):
- return item
- def keys(self):
- return [1,2,3]
-
-#&lt;/dictmixin.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from dictmixin import TracedDM
-&gt;&gt;&gt; print TracedDM()
-calling dictmixin.TracedDM.keys
-calling dictmixin.TracedDM.__getitem__
-calling dictmixin.TracedDM.__getitem__
-calling dictmixin.TracedDM.__getitem__
-{1: 1, 2: 2, 3: 3}
-</pre>
-</div>
-<div class="section" id="real-life-example-check-overriding">
-<h3><a class="toc-backref" href="#id46" name="real-life-example-check-overriding">Real life example: check overriding</a></h3>
-<pre class="literal-block">
-#&lt;check_overriding.py&gt;
-
-class Base(object):
- a = 0
-
-class CheckOverriding(type):
- &quot;Prints a message if we are overriding a name.&quot;
- def __new__(mcl, name, bases, dic):
- for name, val in dic.iteritems():
- if name.startswith(&quot;__&quot;) and name.endswith(&quot;__&quot;):
- continue # ignore special names
- a_base_has_name = True in (hasattr(base, name) for base in bases)
- if a_base_has_name:
- print &quot;AlreadyDefinedNameWarning: &quot; + name
- return super(CheckOverriding, mcl).__new__(mcl, name, bases, dic)
-
-class MyClass(Base):
- __metaclass__ = CheckOverriding
- a = 1
-
-class ChildClass(MyClass):
- a = 2
-</pre>
-<p>#&lt;/check_overriding.py&gt;</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; import check_overriding
-AlreadyDefinedNameWarning: a
-AlreadyDefinedNameWarning: a
-</pre>
-</div>
-<div class="section" id="logfile">
-<h3><a class="toc-backref" href="#id47" name="logfile">LogFile</a></h3>
-<pre class="literal-block">
-#&lt;logfile.py&gt;
-
-import subprocess
-
-def memoize(func):
- memoize_dic = {}
- def wrapped_func(*args):
- if args in memoize_dic:
- return memoize_dic[args]
- else:
- result = func(*args)
- memoize_dic[args] = result
- return result
- wrapped_func.__name__ = func.__name__
- wrapped_func.__doc__ = func.__doc__
- wrapped_func.__dict__ = func.__dict__
- return wrapped_func
-
-class Memoize(type): # Singleton is a special case of Memoize
- &#64;memoize
- def __call__(cls, *args):
- return super(Memoize, cls).__call__(*args)
-
-class LogFile(file):
- &quot;&quot;&quot;Open a file for append.&quot;&quot;&quot;
- __metaclass__ = Memoize
- def __init__(self, name = &quot;/tmp/err.log&quot;):
- self.viewer_cmd = 'xterm -e less'.split()
- super(LogFile, self).__init__(name, &quot;a&quot;)
-
- def display(self, *ls):
- &quot;Use 'less' to display the log file in a separate xterm.&quot;
- print &gt;&gt; self, &quot;\n&quot;.join(map(str, ls)); self.flush()
- subprocess.call(self.viewer_cmd + [self.name])
-
- def reset(self):
- &quot;Erase the log file.&quot;
- print &gt;&gt; file(self.name, &quot;w&quot;)
-
-if __name__ == &quot;__main__&quot;: # test
- print &gt;&gt; LogFile(), &quot;hello&quot;
- print &gt;&gt; LogFile(), &quot;world&quot;
- LogFile().display()
-
-#&lt;/logfile.py&gt;
-
-$ python logfile.py
-</pre>
-</div>
-<div class="section" id="cooperative-hierarchies">
-<h3><a class="toc-backref" href="#id48" name="cooperative-hierarchies">Cooperative hierarchies</a></h3>
-<pre class="literal-block">
-#&lt;cooperative_init.py&gt;
-
-&quot;&quot;&quot;Given a hierarchy, makes __init__ cooperative.
-The only change needed is to add a line
-
- __metaclass__ = CooperativeInit
-
-to the base class of your hierarchy.&quot;&quot;&quot;
-
-from decorators import decorator
-
-class CooperativeInit(type):
- def __init__(cls, name, bases, dic):
-
- &#64;decorator
- def make_cooperative(__init__, self, *args, **kw):
- super(cls, self).__init__(*args, **kw)
- __init__(self, *args, **kw)
-
- __init__ = dic.get(&quot;__init__&quot;)
- if __init__:
- cls.__init__ = make_cooperative(__init__)
-
-class Base:
- __metaclass__ = CooperativeInit
- def __init__(self):
- print &quot;B.__init__&quot;
-
-class C1(Base):
- def __init__(self):
- print &quot;C1.__init__&quot;
-
-class C2(Base):
- def __init__(self):
- print &quot;C2.__init__&quot;
-
-class D(C1, C2):
- def __init__(self):
- print &quot;D.__init__&quot;
-
-#&lt;/cooperative_init.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from cooperative_init import D
-&gt;&gt;&gt; d = D()
-B.__init__
-C2.__init__
-C1.__init__
-D.__init__
-</pre>
-</div>
-<div class="section" id="metaclass-enhanced-modules">
-<h3><a class="toc-backref" href="#id49" name="metaclass-enhanced-modules">Metaclass-enhanced modules</a></h3>
-<pre class="literal-block">
-#&lt;import_with_metaclass.py&gt;
-&quot;&quot;&quot;
-``import_with_metaclass(metaclass, modulepath)`` generates
-a new module from and old module, by enhancing all of its classes.
-This is not perfect, but it should give you a start.&quot;&quot;&quot;
-
-import os, sys, inspect, types
-
-def import_with_metaclass(metaclass, modulepath):
- modname = os.path.basename(modulepath)[:-3] # simplistic
- mod = types.ModuleType(modname)
- locs = dict(
- __module__ = modname,
- __metaclass__ = metaclass,
- object = metaclass(&quot;object&quot;, (), {}))
- execfile(modulepath, locs)
- for k, v in locs.iteritems():
- if inspect.isclass(v): # otherwise it would be &quot;__builtin__&quot;
- v.__module__ = &quot;__dynamic__&quot;
- setattr(mod, k, v)
- return mod
-</pre>
-<p>#&lt;/import_with_metaclass.py&gt;</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; from import_with_metaclass import import_with_metaclass
-&gt;&gt;&gt; from metatracer import MetaTracer
-&gt;&gt;&gt; traced_optparse = import_with_metaclass(MetaTracer,
-... &quot;/usr/lib/python2.4/optparse.py&quot;)
-&gt;&gt;&gt; op = traced_optparse.OptionParser()
-calling __dynamic__.OptionParser.__init__
-calling __dynamic__.OptionContainer.__init__
-calling __dynamic__.OptionParser._create_option_list
-calling __dynamic__.OptionContainer._create_option_mappings
-calling __dynamic__.OptionContainer.set_conflict_handler
-calling __dynamic__.OptionContainer.set_description
-calling __dynamic__.OptionParser.set_usage
-calling __dynamic__.IndentedHelpFormatter.__init__
-calling __dynamic__.HelpFormatter.__init__
-calling __dynamic__.HelpFormatter.set_parser
-calling __dynamic__.OptionParser._populate_option_list
-calling __dynamic__.OptionParser._add_help_option
-calling __dynamic__.OptionContainer.add_option
-calling __dynamic__.Option.__init__
-calling __dynamic__.Option._check_opt_strings
-calling __dynamic__.Option._set_opt_strings
-calling __dynamic__.Option._set_attrs
-calling __dynamic__.OptionContainer._check_conflict
-calling __dynamic__.OptionParser._init_parsing_state
-</pre>
-<p>traced_optparse is a dynamically generated module not leaving in the
-file system.</p>
-</div>
-<div class="section" id="magic-properties">
-<h3><a class="toc-backref" href="#id50" name="magic-properties">Magic properties</a></h3>
-<pre class="literal-block">
-#&lt;magicprop.py&gt;
-
-class MagicProperties(type):
- def __init__(cls, name, bases, dic):
- prop_names = set(name[3:] for name in dic
- if name.startswith(&quot;get&quot;)
- or name.startswith(&quot;set&quot;))
- for name in prop_names:
- getter = getattr(cls, &quot;get&quot; + name, None)
- setter = getattr(cls, &quot;set&quot; + name, None)
- setattr(cls, name, property(getter, setter))
-
-class Base(object):
- __metaclass__ = MagicProperties
- def getx(self):
- return self._x
- def setx(self, value):
- self._x = value
-
-class Child(Base):
- def getx(self):
- print &quot;getting x&quot;
- return super(Child, self).getx()
- def setx(self, value):
- print &quot;setting x&quot;
- super(Child, self).setx(value)
-
-#&lt;/magicprop.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from magicprop import Child
-&gt;&gt;&gt; c = Child()
-&gt;&gt;&gt; c.x = 1
-setting x
-&gt;&gt;&gt; print c.x
-getting x
-1
-</pre>
-</div>
-<div class="section" id="hack-evil-properties">
-<h3><a class="toc-backref" href="#id51" name="hack-evil-properties">Hack: evil properties</a></h3>
-<pre class="literal-block">
-#&lt;evilprop.py&gt;
-
-def convert2property(name, bases, d):
- return property(d.get('get'), d.get('set'),
- d.get('del'),d.get('__doc__'))
-
-class C(object):
- class x:
- &quot;&quot;&quot;An evil test property&quot;&quot;&quot;
- __metaclass__ = convert2property
- def get(self):
- print 'Getting %s' % self._x
- return self._x
- def set(self, value):
- self._x = value
- print 'Setting to', value
-
-#&lt;/evilprop.py&gt;
-</pre>
-<pre class="doctest-block">
-&gt;&gt;&gt; from evilprop import C
-&gt;&gt;&gt; c = C()
-&gt;&gt;&gt; c.x = 5
-Setting to 5
-&gt;&gt;&gt; c.x
-Getting 5
-5
-&gt;&gt;&gt; print C.x.__doc__
-An evil test property
-</pre>
-</div>
-<div class="section" id="why-i-suggest-not-to-use-metaclasses-in-production-code">
-<h3><a class="toc-backref" href="#id52" name="why-i-suggest-not-to-use-metaclasses-in-production-code">Why I suggest <em>not</em> to use metaclasses in production code</a></h3>
-<blockquote>
-<ul class="simple">
-<li>there are very few good use case for metaclasses in production code
-(i.e. 99% of time you don't need them)</li>
-<li>they put a cognitive burden on the developer;</li>
-<li>a design without metaclasses is less magic and likely more robust;</li>
-<li>a design with metaclasses makes it difficult to use other metaclasses
-for debugging.</li>
-</ul>
-</blockquote>
-<p>As far as I know, string.Template is the only metaclass-enhanced class
-in the standard library; the metaclass is used to give the possibility to
-change the defaults:</p>
-<pre class="literal-block">
-delimiter = '$'
-idpattern = r'[_a-z][_a-z0-9]*'
-</pre>
-<p>in subclasses of Template.</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; from string import Template
-&gt;&gt;&gt; from metatracer import MetaTracer
-&gt;&gt;&gt; class TracedTemplate(Template):
-... __metaclass__ = MetaTracer
-...
-Traceback (most recent call last):
- ...
-TypeError: Error when calling the metaclass bases
- metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
-</pre>
-<p>Solution: use a consistent metaclass</p>
-<pre class="doctest-block">
-&gt;&gt;&gt; class GoodMeta(MetaTracer, type(Template)): pass
-...
-&gt;&gt;&gt; class TracedTemplate(Template):
-... __metaclass__ = GoodMeta
-</pre>
-</div>
-<div class="section" id="is-there-an-automatic-way-of-solving-the-conflict">
-<h3><a class="toc-backref" href="#id53" name="is-there-an-automatic-way-of-solving-the-conflict">Is there an automatic way of solving the conflict?</a></h3>
-<p>Yes, but you really need to be a metaclass wizard.</p>
-<p><a class="reference" href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/204197">http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/204197</a></p>
-<pre class="doctest-block">
-&gt;&gt;&gt; from noconflict import classmaker
-&gt;&gt;&gt; class TracedTemplate(Template):
-... __metaclass__ = classmaker((MetaTracer,))
-&gt;&gt;&gt; print type(TracedTemplate)
-&lt;class 'noconflict._MetaTracer_TemplateMetaclass'&gt;
-</pre>
-<pre class="literal-block">
-#&lt;noconflict.py&gt;
-
-import inspect, types, __builtin__
-from skip_redundant import skip_redundant
-
-memoized_metaclasses_map = {}
-
-# utility function
-def remove_redundant(metaclasses):
- skipset = set([types.ClassType])
- for meta in metaclasses: # determines the metaclasses to be skipped
- skipset.update(inspect.getmro(meta)[1:])
- return tuple(skip_redundant(metaclasses, skipset))
-
-##################################################################
-## now the core of the module: two mutually recursive functions ##
-##################################################################
-
-def get_noconflict_metaclass(bases, left_metas, right_metas):
- &quot;&quot;&quot;Not intended to be used outside of this module, unless you know
- what you are doing.&quot;&quot;&quot;
- # make tuple of needed metaclasses in specified priority order
- metas = left_metas + tuple(map(type, bases)) + right_metas
- needed_metas = remove_redundant(metas)
-
- # return existing confict-solving meta, if any
- if needed_metas in memoized_metaclasses_map:
- return memoized_metaclasses_map[needed_metas]
- # nope: compute, memoize and return needed conflict-solving meta
- elif not needed_metas: # wee, a trivial case, happy us
- meta = type
- elif len(needed_metas) == 1: # another trivial case
- meta = needed_metas[0]
- # check for recursion, can happen i.e. for Zope ExtensionClasses
- elif needed_metas == bases:
- raise TypeError(&quot;Incompatible root metatypes&quot;, needed_metas)
- else: # gotta work ...
- metaname = '_' + ''.join([m.__name__ for m in needed_metas])
- meta = classmaker()(metaname, needed_metas, {})
- memoized_metaclasses_map[needed_metas] = meta
- return meta
-
-def classmaker(left_metas=(), right_metas=()):
- def make_class(name, bases, adict):
- metaclass = get_noconflict_metaclass(bases, left_metas, right_metas)
- return metaclass(name, bases, adict)
- return make_class
-
-#################################################################
-## and now a conflict-safe replacement for 'type' ##
-#################################################################
-
-__type__=__builtin__.type # the aboriginal 'type'
-# left available in case you decide to rebind __builtin__.type
-
-class safetype(__type__):
- # this is REALLY DEEP MAGIC
- &quot;&quot;&quot;Overrides the ``__new__`` method of the ``type`` metaclass, making the
- generation of classes conflict-proof.&quot;&quot;&quot;
- def __new__(mcl, *args):
- nargs = len(args)
- if nargs == 1: # works as __builtin__.type
- return __type__(args[0])
- elif nargs == 3: # creates the class using the appropriate metaclass
- n, b, d = args # name, bases and dictionary
- meta = get_noconflict_metaclass(b, (mcl,), ())
- if meta is mcl: # meta is trivial, dispatch to the default __new__
- return super(safetype, mcl).__new__(mcl, n, b, d)
- else: # non-trivial metaclass, dispatch to the right __new__
- # (it will take a second round) # print mcl, meta
- return super(mcl, meta).__new__(meta, n, b, d)
- else:
- raise TypeError('%s() takes 1 or 3 arguments' % mcl.__name__)
-
-#&lt;/noconflict.py&gt;
-</pre>
-</div>
-</div>
-</div>
-</div>
-</body>
-</html>