Commits

Anonymous committed e82df5b Draft

finished lists section of "native datatypes"

Comments (0)

Files changed (4)

 
 """
 
-SUFFIXES = {1000: ('KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'),
-            1024: ('KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB')}
+SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
+            1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}
 
 def approximate_size(size, a_kilobyte_is_1024_bytes=True):
     """Convert a file size to human-readable form.

native-datatypes.html

 <li>If both slice indices are left out, all items of the list are included. But this is not the same as the original <var>a_list</var> variable. It is a new list that happens to have all the same items. <code>a_list[:]</code> is shorthand for making a complete copy of a list.
 </ol>
 <h3 id=extendinglists>Adding items to a list</h3>
-<p>Lists are implemented as classes.  &#8220;Creating&#8221; a list is really instantiating a class.  As such, a list has methods that operate on it.
-<pre class=screen><samp class=prompt>>>> </samp><kbd>a_list</kbd>
-<samp>['a', 'b', 'mpilgrim', 'z', 'example']</samp>
-<a><samp class=prompt>>>> </samp><kbd>a_list.append('new')</kbd>             <span>&#x2460;</span></a>
+<p>There are four ways to add items to a list.
+<pre class=screen>
+<samp class=prompt>>>> </samp><kbd>a_list = ['a']</kbd>
+<a><samp class=prompt>>>> </samp><kbd>a_list = a_list + [2.0, 3]</kbd>    <span>&#x2460;</span></a>
 <samp class=prompt>>>> </samp><kbd>a_list</kbd>
-<samp>['a', 'b', 'mpilgrim', 'z', 'example', 'new']</samp>
-<a><samp class=prompt>>>> </samp><kbd>a_list.insert(2, 'new')</kbd>          <span>&#x2461;</span></a>
+<samp>['a', 2.0, 3]</samp>
+<a><samp class=prompt>>>> </samp><kbd>a_list.append(True)</kbd>           <span>&#x2461;</span></a>
 <samp class=prompt>>>> </samp><kbd>a_list</kbd>
-<samp>['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new']</samp>
-<a><samp class=prompt>>>> </samp><kbd>a_list.extend(['two', 'items'])</kbd>  <span>&#x2462;</span></a>
+<samp>['a', 2.0, 3, True]</samp>
+<a><samp class=prompt>>>> </samp><kbd>a_list.extend(['four', 'e'])</kbd>  <span>&#x2462;</span></a>
 <samp class=prompt>>>> </samp><kbd>a_list</kbd>
-<samp>['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'items']</samp></pre>
+<samp>['a', 2.0, 3, True, 'four', 'e']</samp>
+<a><samp class=prompt>>>> </samp><kbd>a_list.insert(1, 'a')</kbd>         <span>&#x2463;</span></a>
+<samp class=prompt>>>> </samp><kbd>a_list</kbd>
+<samp>['a', 'a', 2.0, 3, True, 'four', 'e']</samp></pre>
 <ol>
-<li>The <code>append()</code> method adds a single item to the end of the list.
-<li>The <code>insert()</code> method inserts a single item into a list. The numeric argument is the index of the first item that gets bumped out of position. List items do not need to be unique; for example, there are now two separate items with the value <code>'new'</code>, <code>a_list[2]</code> and <code>a_list[6]</code>.
-<li>The <code>extend()</code> method concatenates lists. You do not call <code>extend()</code> with multiple arguments; you call it with one argument, a list. In this case, that list has two items.
+<li>The <code>+</code> operator concatenates lists. A list can contain any number of items; there is no size limit (other than available memory). A list can contain items of any datatype; they don't all need to be the same type. Here we have a list containing a string, a floating point number, and an integer.
+<li>The <code>append()</code> method adds a single item to the end of the list. (Now we have <em>four</em> different datatypes in the list!)
+<li>Lists are implemented as classes.  &#8220;Creating&#8221; a list is really instantiating a class.  As such, a list has methods that operate on it. The <code>extend()</code> method takes one argument, a list, and appends each of the items of the argument to the original list.
+<li>The <code>insert()</code> method inserts a single item into a list. The first argument is the index of the first item in the list that will get bumped out of position. List items do not need to be unique; for example, there are now two separate items with the value <code>'a'</code>, <code>a_list[0]</code> and <code>a_list[1]</code>.
 </ol>
-<p>That last bit is subtle but important. Let's look closer at the difference between <code>extend()</code> and <code>append()</code>.
+<p>Let's look closer at the difference between <code>append()</code> and <code>extend()</code>.
 <pre class=screen>
 <samp class=prompt>>>> </samp><kbd>a_list = ['a', 'b', 'c']</kbd>
 <a><samp class=prompt>>>> </samp><kbd>a_list.extend(['d', 'e', 'f'])</kbd>  <span>&#x2460;</span></a>
 <li>The <code>index()</code> method finds the <em>first</em> occurrence of a value in the list. In this case, <code>'new'</code> occurs twice in the list, in <code>a_list[2]</code> and <code>a_list[4]</code>, but the <code>index()</code> method will return only the index of the first occurrence.
 <li>As you might <em>not</em> expect, if the value is not found in the list, Python raises an exception. This is notably different from most languages, which will return some invalid index (like <code>-1</code>). While this may seem annoying at first, I think you will come to appreciate it. It means your program will crash at the source of the problem instead of failing strangely and silently later.
 </ol>
-<!--
-<h3>3.2.4. Deleting List Items</h3>
-<div class="example"><h3 id=odbchelper.list.removingitems>Example 3.13. Removing Items from a List</h3><pre class=screen><samp class=prompt>>>> </samp>a_list
-['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'items']
-<samp class=prompt>>>> </samp>a_list.remove("z")   <img id=odbchelper.list.7.1" src="images/callouts/1.png" alt="1" border="0" width="12" height="12>
-<samp class=prompt>>>> </samp>a_list
-['a', 'b', 'new', 'mpilgrim', 'example', 'new', 'two', 'items']
-<samp class=prompt>>>> </samp>a_list.remove("new") <img id=odbchelper.list.7.2" src="images/callouts/2.png" alt="2" border="0" width="12" height="12>
-<samp class=prompt>>>> </samp>a_list
-['a', 'b', 'mpilgrim', 'example', 'new', 'two', 'items']
-<samp class=prompt>>>> </samp>a_list.remove("c")   <img id=odbchelper.list.7.3" src="images/callouts/3.png" alt="3" border="0" width="12" height="12>
-<samp class="traceback">Traceback (innermost last):
-  File "&lt;interactive input>", line 1, in ?
-ValueError: list.remove(x): x not in list</samp>
-<samp class=prompt>>>> </samp>a_list.pop()         <img id=odbchelper.list.7.4" src="images/callouts/4.png" alt="4" border="0" width="12" height="12>
-'items'
-<samp class=prompt>>>> </samp>a_list
-['a', 'b', 'mpilgrim', 'example', 'new', 'two']</pre><div class="calloutlist">
-<table border="0" summary="Callout list">
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.list.7.1><img src="images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left"><code>remove</code> removes the first occurrence of a value from a list.
-</td>
-</tr>
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.list.7.2><img src="images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left"><code>remove</code> removes <em>only</em> the first occurrence of a value. In this case, <code>'new'</code> appeared twice in the list, but <code>a_list.remove("new")</code> removed only the first occurrence.
-</td>
-</tr>
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.list.7.3><img src="images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left">If the value is not found in the list, Python raises an exception. This mirrors the behavior of the <code>index</code> method.
-</td>
-</tr>
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.list.7.4><img src="images/callouts/4.png" alt="4" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left"><code>pop</code> is an interesting beast. It does two things: it removes the last item of the list, and it returns the value that it removed.
-                Note that this is different from <code>a_list[-1]</code>, which returns a value but does not change the list, and different from <code>a_list.remove(<var>value</var>)</code>, which changes the list but does not return a value.
-</td>
-</tr>
-</table>
-<h3>3.2.5. Using List Operators</h3>
-<div class="example"><h3 id=odbchelper.list.operators>Example 3.14. List Operators</h3><pre class=screen><samp class=prompt>>>> </samp>a_list = ['a', 'b', 'mpilgrim']
-<samp class=prompt>>>> </samp>a_list = a_list + ['example', 'new'] <img id=odbchelper.list.8.1" src="images/callouts/1.png" alt="1" border="0" width="12" height="12>
-<samp class=prompt>>>> </samp>a_list
-['a', 'b', 'mpilgrim', 'example', 'new']
-<samp class=prompt>>>> </samp>a_list += ['two']                <img id=odbchelper.list.8.2" src="images/callouts/2.png" alt="2" border="0" width="12" height="12>
-<samp class=prompt>>>> </samp>a_list
-['a', 'b', 'mpilgrim', 'example', 'new', 'two']
-<samp class=prompt>>>> </samp>a_list = [1, 2] * 3              <img id=odbchelper.list.8.3" src="images/callouts/3.png" alt="3" border="0" width="12" height="12>
-<samp class=prompt>>>> </samp>a_list
-[1, 2, 1, 2, 1, 2]</pre><div class="calloutlist">
-<table border="0" summary="Callout list">
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.list.8.1><img src="images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left">Lists can also be concatenated with the <code>+</code> operator. <code><var>list</var> = <var>list</var> + <var>otherlist</var></code> has the same result as <code><var>list</var>.extend(<var>otherlist</var>)</code>. But the <code>+</code> operator returns a new (concatenated) list as a value, whereas <code>extend</code> only alters an existing list. This means that <code>extend</code> is faster, especially for large lists.
-</td>
-</tr>
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.list.8.2><img src="images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left">Python supports the <code>+=</code> operator. <code>a_list += ['two']</code> is equivalent to <code>a_list.extend(['two'])</code>. The <code>+=</code> operator works for lists, strings, and integers, and it can be overloaded to work for user-defined classes as well. (More
-               on classes in <a href=#fileinfo>Chapter 5</a>.)
-</td>
-</tr>
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.list.8.3><img src="images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left">The <code>*</code> operator works on lists as a repeater. <code>a_list = [1, 2] * 3</code> is equivalent to <code>a_list = [1, 2] + [1, 2] + [1, 2]</code>, which concatenates the three lists into one.
-</td>
-</tr>
-</table>
-<div class="itemizedlist">
-<h3>Further Reading on Lists</h3>
-<ul>
-<li><a href=http://www.ibiblio.org/obp/thinkCSpy/" title="Python book for computer science majors><i class="citetitle">How to Think Like a Computer Scientist</i></a> teaches about lists and makes an important point about <a href=http://www.ibiblio.org/obp/thinkCSpy/chap08.htm>passing lists as function arguments</a>.
-
-<li><a href=http://www.python.org/doc/current/tut/tut.html><i class="citetitle">Python Tutorial</i></a> shows how to <a href=http://www.python.org/doc/current/tut/node7.html#SECTION007110000000000000000>use lists as stacks and queues</a>.
-
-<li><a href=http://www.faqts.com/knowledge-base/index.phtml/fid/199/>Python Knowledge Base</a> answers <a href=http://www.faqts.com/knowledge-base/index.phtml/fid/534>common questions about lists</a> and has a lot of <a href=http://www.faqts.com/knowledge-base/index.phtml/fid/540>example code using lists</a>.
-
-<li><a href=http://www.python.org/doc/current/lib/><i class="citetitle">Python Library Reference</i></a> summarizes <a href=http://www.python.org/doc/current/lib/typesseq-mutable.html>all the list methods</a>.
-
-</ul>
-<h2 id=odbchelper.tuple>3.3. Introducing Tuples</h2>
-<p>A tuple is an immutable list. A tuple can not be changed in any way once it is created.
-<div class="example"><h3>Example 3.15. Defining a tuple</h3><pre class=screen><samp class=prompt>>>> </samp>t = ("a", "b", "mpilgrim", "z", "example") <img id=odbchelper.tuple.1.1" src="images/callouts/1.png" alt="1" border="0" width="12" height="12>
-<samp class=prompt>>>> </samp>t
-('a', 'b', 'mpilgrim', 'z', 'example')
-<samp class=prompt>>>> </samp>t[0]   <img id=odbchelper.tuple.1.2" src="images/callouts/2.png" alt="2" border="0" width="12" height="12>
-'a'
-<samp class=prompt>>>> </samp>t[-1]  <img id=odbchelper.tuple.1.3" src="images/callouts/3.png" alt="3" border="0" width="12" height="12>
-'example'
-<samp class=prompt>>>> </samp>t[1:3] <img id=odbchelper.tuple.1.4" src="images/callouts/4.png" alt="4" border="0" width="12" height="12>
-('b', 'mpilgrim')</pre><div class="calloutlist">
-<table border="0" summary="Callout list">
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.tuple.1.1><img src="images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left">A tuple is defined in the same way as a list, except that the whole set of items is enclosed in parentheses instead of
-            square brackets.
-</td>
-</tr>
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.tuple.1.2><img src="images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left">The items of a tuple have a defined order, just like a list. Tuples indices are zero-based, just like a list, so the first
-            item of a non-empty tuple is always <code>t[0]</code>.
-</td>
-</tr>
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.tuple.1.3><img src="images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left">Negative indices count from the end of the tuple, just as with a list.</td>
-</tr>
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.tuple.1.4><img src="images/callouts/4.png" alt="4" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left">Slicing works too, just like a list. Note that when you slice a list, you get a new list; when you slice a tuple, you get
-            a new tuple.
-</td>
-</tr>
-</table>
-<div class="example"><h3 id=odbchelper.tuplemethods>Example 3.16. Tuples Have No Methods</h3><pre class=screen><samp class=prompt>>>> </samp>t
-('a', 'b', 'mpilgrim', 'z', 'example')
-<samp class=prompt>>>> </samp>t.append("new")    <img id=odbchelper.tuple.2.1" src="images/callouts/1.png" alt="1" border="0" width="12" height="12>
-<samp class="traceback">Traceback (innermost last):
-  File "&lt;interactive input>", line 1, in ?
-AttributeError: 'tuple' object has no attribute 'append'</samp>
-<samp class=prompt>>>> </samp>t.remove("z")      <img id=odbchelper.tuple.2.2" src="images/callouts/2.png" alt="2" border="0" width="12" height="12>
-<samp class="traceback">Traceback (innermost last):
-  File "&lt;interactive input>", line 1, in ?
-AttributeError: 'tuple' object has no attribute 'remove'</samp>
-<samp class=prompt>>>> </samp>t.index("example") <img id=odbchelper.tuple.2.3" src="images/callouts/3.png" alt="3" border="0" width="12" height="12>
-<samp class="traceback">Traceback (innermost last):
-  File "&lt;interactive input>", line 1, in ?
-AttributeError: 'tuple' object has no attribute 'index'</samp>
-<samp class=prompt>>>> </samp>"z" in t           <img id=odbchelper.tuple.2.4" src="images/callouts/4.png" alt="4" border="0" width="12" height="12>
-True</pre><div class="calloutlist">
-<table border="0" summary="Callout list">
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.tuple.2.1><img src="images/callouts/1.png" alt="1" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left">You can't add items to a tuple. Tuples have no <code>append</code> or <code>extend</code> method.
-</td>
-</tr>
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.tuple.2.2><img src="images/callouts/2.png" alt="2" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left">You can't remove items from a tuple. Tuples have no <code>remove</code> or <code>pop</code> method.
-</td>
-</tr>
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.tuple.2.3><img src="images/callouts/3.png" alt="3" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left">You can't find items in a tuple. Tuples have no <code>index</code> method.
-</td>
-</tr>
-<tr>
-<td width="12" valign="top" align="left"><a href=#odbchelper.tuple.2.4><img src="images/callouts/4.png" alt="4" border="0" width="12" height="12"></a> 
-</td>
-<td valign="top" align="left">You can, however, use <code>in</code> to see if an item exists in the tuple.
-</td>
-</tr>
-</table>
-<p>So what are tuples good for?
-<div class="itemizedlist">
-<ul>
-<li>Tuples are faster than lists. If you're defining a constant set of values and all you're ever going to do with it is iterate
-      through it, use a tuple instead of a list.
-
-<li>It makes your code safer if you &#8220;write-protect&#8221; data that does not need to be changed. Using a tuple instead of a list is like having an implied <code>assert</code> statement that shows this data is constant, and that special thought (and a specific function) is required to override that.
-
-<li>Remember that I said that <a href=#odbchelper.dictionarytypes" title="Example 3.4. Mixing Datatypes in a Dictionary>dictionary keys</a> can be integers, strings, and &#8220;a few other types&#8221;?  Tuples are one of those types. Tuples can be used as keys in a dictionary, but lists can't be used this way.Actually, it's more complicated than that. Dictionary keys must be immutable. Tuples themselves are immutable, but if you
-      have a tuple of lists, that counts as mutable and isn't safe to use as a dictionary key. Only tuples of strings, numbers,
-      or other dictionary-safe tuples can be used as dictionary keys.
-
-<li>Tuples are used in string formatting, as you'll see shortly.
-</ul>
-</div><table id=tip.tuple" class="note" border="0" summary=">
-<tr>
-<td colspan="2" align="left" valign="top" width="99%">Tuples can be converted into lists, and vice-versa. The built-in <code>tuple</code> function takes a list and returns a tuple with the same items, and the <code>list</code> function takes a tuple and returns a list. In effect, <code>tuple</code> freezes a list, and <code>list</code> thaws a tuple.
-</td>
-</tr>
-</table>
-<div class="itemizedlist">
-<h3>Further Reading on Tuples</h3>
-<ul>
-<li><a href=http://www.ibiblio.org/obp/thinkCSpy/" title="Python book for computer science majors><i class="citetitle">How to Think Like a Computer Scientist</i></a> teaches about tuples and shows how to <a href=http://www.ibiblio.org/obp/thinkCSpy/chap10.htm>concatenate tuples</a>.
-
-<li><a href=http://www.faqts.com/knowledge-base/index.phtml/fid/199/>Python Knowledge Base</a> shows how to <a href=http://www.faqts.com/knowledge-base/view.phtml/aid/4553/fid/587>sort a tuple</a>.
-
-<li><a href=http://www.python.org/doc/current/tut/tut.html><i class="citetitle">Python Tutorial</i></a> shows how to <a href=http://www.python.org/doc/current/tut/node7.html#SECTION007300000000000000000>define a tuple with one item</a>.
-
-</ul>
--->
 <h2 id=sets>Sets</h2>
 <p>FIXME
 <h2 id=dictionaries>Dictionaries</h2>
             1024: ('KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB')}</code></pre>
 <p>Let's tear that apart in the interactive shell.
 <pre class=screen>
-<samp class=prompt>>>> </samp><kbd>SUFFIXES = {1000: ('KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'),</kbd>
-<samp class=prompt>... </samp><kbd>            1024: ('KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB')}</kbd>
+<samp class=prompt>>>> </samp><kbd>SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],</kbd>
+<samp class=prompt>... </samp><kbd>            1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}</kbd>
 <a><samp class=prompt>>>> </samp><kbd>len(SUFFIXES)</kbd>      <span>&#x2460;</span></a>
 <samp>2</samp>
 <a><samp class=prompt>>>> </samp><kbd>SUFFIXES[1000]</kbd>     <span>&#x2461;</span></a>
-<samp>('KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB')</samp>
+<samp>['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']</samp>
 <a><samp class=prompt>>>> </samp><kbd>SUFFIXES[1024]</kbd>     <span>&#x2462;</span></a>
-<samp>('KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB')</samp>
+<samp>['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']</samp>
 <a><samp class=prompt>>>> </samp><kbd>SUFFIXES[1000][3]</kbd>  <span>&#x2463;</span></a>
 <samp>'TB'</samp></pre>
 <ol>
 <li>As with <a href=#lists>lists</a> and <a href=#sets>sets</a>, the <code>len()</code> function gives you the number of items in a dictionary.
-<li><code>1000</code> is a key in the <code>SUFFIXES</code> dictionary; its value is a tuple of eight items (eight strings, to be precise).
-<li>Similarly, <code>1024</code> is a key in the <code>SUFFIXES</code> dictionary; its value is also a tuple of eight items.
-<li>Since <code>SUFFIXES[1000]</code> is a tuple, you can address individual items in the tuple by their 0-based index.
+<li><code>1000</code> is a key in the <code>SUFFIXES</code> dictionary; its value is a list of eight items (eight strings, to be precise).
+<li>Similarly, <code>1024</code> is a key in the <code>SUFFIXES</code> dictionary; its value is also a list of eight items.
+<li>Since <code>SUFFIXES[1000]</code> is a list, you can address individual items in the list by their 0-based index.
 </ol>
 <h2 id=none><code>None</code></h2>
 <p><code>None</code> is a special constant in Python. It is a null value. <code>None</code> is not <code>False</code>; it is not <code>0</code>; it is not an empty string. Comparing <code>None</code> to anything other than <code>None</code> will always return <code>False</code>.
 <samp class=prompt>>>> </samp><kbd>x == y</kbd>
 <samp>True</samp>
 </pre>
-<h3 id=furtherreading>Further reading</h3>
+<h2 id=furtherreading>Further reading</h2>
 <ul>
 <li>fractions
 <li>math module

porting-code-to-python-3-with-2to3.html

 <li>If you used to call <code>xreadlines()</code> with no arguments, <code>2to3</code> will convert it to just the file object. In Python 3, this will accomplish the same thing: read the file one line at a time and execute the body of the <code>for</code> loop.
 <li>If you used to call <code>xreadlines()</code> with an argument (the number of lines to read at a time), keep doing that. It still works in Python 3, and <code>2to3</code> will not change it.
 </ol>
+<p class=c><span style="font-size:56px;line-height:0.88">&#x2603;</span>
 <h2 id=tuple_params><code>lambda</code> functions with multiple parameters</h2>
 <p>In Python 2, you could define anonymous <code>lambda</code> functions which took multiple parameters by defining the function as taking a tuple with a specific number of items. In effect, Python 2 would &#8220;unpack&#8221; the tuple into named arguments, which you could then reference (by name) within the <code>lambda</code> function. In Python 3, you can still pass a tuple to a <code>lambda</code> function, but the Python interpreter will not unpack the tuple into named arguments. Instead, you will need to reference each argument by its positional index.
 <p class=skip><a href=#skipcomparetuple_params>skip over this table</a>

your-first-python-program.html

 </ol>
 <h2 id=divingin>Diving in</h2>
 <p class=fancy>You know how other books go on and on about programming fundamentals and finally work up to building something useful?  Let's skip all that. Here is a complete, working Python program. It probably makes absolutely no sense to you. Don't worry about that, because you're going to dissect it line by line. But read through it first and see what, if anything, you can make of it.
-<!-- FIXME: download link -->
 <p class=download>[<a href=humansize.py>download</a>]</p>
-<pre><code>SUFFIXES = {1000: ('KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'),
-            1024: ('KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB')}
+<pre><code>SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
+            1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}
 
 def approximate_size(size, a_kilobyte_is_1024_bytes=True):
     """Convert a file size to human-readable form.
 <pre class=screen><samp class=prompt>c:\home\diveintopython3> </samp><kbd>c:\python30\python.exe humansize.py</kbd>
 <samp>1.0 TB
 931.3 GiB</samp></pre>
-<h3 id=furtherreading>Further reading</h3>
+<h2 id=furtherreading>Further reading</h2>
 <ul>
 <li><a href=http://www.python.org/dev/peps/pep-0257/>PEP 257: Docstring Conventions</a> explains what distinguishes a good <code>docstring</code> from a great <code>docstring</code>.
 <li><a href=http://docs.python.org/3.0/tutorial/controlflow.html#documentation-strings>Python Tutorial: Documentation Strings</a> also touches on the subject.