changeset 40:741b0e6cd9ac

Moved some sections around.
author Atul Varma <varmaa@toolness.com>
date Fri, 06 Jun 2008 13:15:22 -0700
parents b3fdf83125c2
children af7d50fc8cfd
files PythonForJsProgrammers.html PythonForJsProgrammers.txt
diffstat 2 files changed, 328 insertions(+), 277 deletions(-) [+]
line wrap: on
line diff
--- a/PythonForJsProgrammers.html	Fri Jun 06 12:54:07 2008 -0700
+++ b/PythonForJsProgrammers.html	Fri Jun 06 13:15:22 2008 -0700
@@ -52,10 +52,10 @@
 something it should already be able to infer from the use of
 whitespace?</p>
 <p>This is actually a violation of the <a class="reference" href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">Don't Repeat Yourself</a> (DRY)
-principle popularized by Andy Hunt and Dave Thomas.  Because unneeded
-extra work is required when moving from a single-line clause to a
+principle popularized by Andy Hunt and Dave Thomas.  Because extra
+work is required when moving from a single-line clause to a
 multiple-line clause, it's a constant source of errors in C-like
-languages, and many stylistic rules and arguments have been spawned as
+languages, and stylistic rules and arguments have been spawned as
 a result of this mistake in language design.</p>
 <p>Python is one of the few languages that takes the simpler and more
 humane approach: whitespace has a consistent semantic meaning to the
@@ -110,7 +110,8 @@
 <p>If there's a function you're interested in learning more about, you
 can look at the built-in documentation metadata associated with the
 object--known as the <cite>docstring</cite>--by querying the object's <tt class="docutils literal"><span class="pre">__doc__</span></tt>
-attribute:</p>
+attribute.  For instance, here's how to get help on the string
+object's <tt class="docutils literal"><span class="pre">join()</span></tt> method:</p>
 <blockquote>
 <pre class="doctest-block">
 &gt;&gt;&gt; print &quot;a string&quot;.join.__doc__
@@ -120,8 +121,7 @@
 sequence.  The separator between elements is S.
 </pre>
 </blockquote>
-<p>This makes it very easy and fun to explore the language and its
-environs.</p>
+<p>This makes it easy and fun to explore the language and its environs.</p>
 </div>
 <div class="section">
 <h1><a id="batteries-included" name="batteries-included">Batteries Included</a></h1>
@@ -152,59 +152,28 @@
 </div>
 <div class="section">
 <h1><a id="strings" name="strings">Strings</a></h1>
-<p>Strings are, unfortunately, the bane of Python programming.  Unlike
-JavaScript, in which every string is unicode, strings in Python are
-really more like immutable arrays of bytes.  Unicode strings are an
-entirely different type, and unicode literals must be prepended with a
-<tt class="docutils literal"><span class="pre">u</span></tt>, like so:</p>
+<p>Strings in Python work a lot like they do in JavaScript, but with some
+added benefits.</p>
+<p>Strings--or any sequence-like object in Python, for that matter--can
+be indexed by character like they can in JavaScript, with the addition
+that negative indexes may be used to denote items from the end of the
+sequence:</p>
 <blockquote>
 <pre class="doctest-block">
-&gt;&gt;&gt; u&quot;I am a unicode string.&quot;
-u'I am a unicode string.'
-&gt;&gt;&gt; &quot;I am a non-unicode string.&quot;
-'I am a non-unicode string.'
-</pre>
-</blockquote>
-<p>The non-intuitiveness of this is due to historical reasons: Python is
-an older language than JavaScript and dates back to 1991, so the
-language didn't originally support unicode.  When support was added,
-it was added in a way that didn't break backwards compatibility.  This
-situation will be resolved in <a class="reference" href="http://www.python.org/dev/peps/pep-3000/">Python 3000</a>, the first version of
-Python to break backwards compatibility with previous versions.</p>
-<p>A string with a character encoding may be converted to a <tt class="docutils literal"><span class="pre">unicode</span></tt>
-object through the <tt class="docutils literal"><span class="pre">decode()</span></tt> method, like so:</p>
-<blockquote>
-<pre class="doctest-block">
-&gt;&gt;&gt; &quot;Here is an ellipsis: \xe2\x80\xa6&quot;.decode(&quot;utf-8&quot;)
-u'Here is an ellipsis: \u2026'
+&gt;&gt;&gt; &quot;Hello&quot;[-1]
+'o'
 </pre>
 </blockquote>
-<p>Conversely, you can convert a <tt class="docutils literal"><span class="pre">unicode</span></tt> object into a string via the
-<tt class="docutils literal"><span class="pre">encode()</span></tt> method:</p>
-<blockquote>
-<pre class="doctest-block">
-&gt;&gt;&gt; u&quot;Here is an ellipsis: \u2026&quot;.encode(&quot;utf-8&quot;)
-'Here is an ellipsis: \xe2\x80\xa6'
-</pre>
-</blockquote>
-<p>An exception will be raised if there are characters that aren't
-supported by the encoding you specify, though:</p>
+<p>Any indexable item can generally also be sliced; this is similar to
+<tt class="docutils literal"><span class="pre">String.slice</span></tt> in JavaScript, only built-in to the language:</p>
 <blockquote>
 <pre class="doctest-block">
-&gt;&gt;&gt; u&quot;hello\u2026&quot;.encode(&quot;ascii&quot;)
-Traceback (most recent call last):
-...
-UnicodeEncodeError: 'ascii' codec can't encode character u'\u2026' in position 5: ordinal not in range(128)
-</pre>
-</blockquote>
-<p>As such, it's a good idea to optionally specify an algorithm to deal
-with characters that aren't supported by the encoding:</p>
-<blockquote>
-<pre class="doctest-block">
-&gt;&gt;&gt; u&quot;hello\u2026&quot;.encode(&quot;ascii&quot;, &quot;ignore&quot;)
-'hello'
-&gt;&gt;&gt; u&quot;hello\u2026&quot;.encode(&quot;ascii&quot;, &quot;xmlcharrefreplace&quot;)
-'hello&amp;#8230;'
+&gt;&gt;&gt; &quot;hello&quot;[2:4]     # Just like &quot;hello&quot;.slice(2,4) in JS
+'ll'
+&gt;&gt;&gt; &quot;hello&quot;[2:]      # Just like &quot;hello&quot;.slice(2) in JS
+'llo'
+&gt;&gt;&gt; &quot;hello&quot;[:4]      # Just like &quot;hello&quot;.slice(0,4) in JS
+'hell'
 </pre>
 </blockquote>
 <p>It's also easy to format strings in Python.  If you're familiar with
@@ -355,7 +324,7 @@
 forth.</p>
 </div>
 <div class="section">
-<h1><a id="global-variables" name="global-variables">Global Variables</a></h1>
+<h1><a id="variables" name="variables">Variables</a></h1>
 <p>Python, like JavaScript, is lexically scoped when it comes to reading
 variables.</p>
 <p>However, Python's scoping rules for assignment to undefined variables
@@ -385,41 +354,6 @@
 explicitly told otherwise.</p>
 </div>
 <div class="section">
-<h1><a id="closures" name="closures">Closures</a></h1>
-<p>Function closures are available in Python:</p>
-<blockquote>
-<pre class="doctest-block">
-&gt;&gt;&gt; def myfunc():
-...     a = 1
-...     def wrapped():
-...         return a
-...     return wrapped
-&gt;&gt;&gt; myfunc()()
-1
-</pre>
-</blockquote>
-<p>Unlike Javascript, however, the variable bindings in the closure are
-&quot;read-only&quot;:</p>
-<blockquote>
-<pre class="doctest-block">
-&gt;&gt;&gt; def myfunc():
-...     a = 1
-...     def wrapped():
-...         a += 1                 # Doesn't work!
-...         return a
-...     return wrapped
-&gt;&gt;&gt; myfunc()()
-Traceback (most recent call last):
-...
-UnboundLocalError: local variable 'a' referenced before assignment
-</pre>
-</blockquote>
-<p>This means that closures can't be used to access private variables
-like they can in JavaScript; instead, everything is visible, and
-implementation-specific variables are conventionally preceded with one
-or two underscores.</p>
-</div>
-<div class="section">
 <h1><a id="sequences" name="sequences">Sequences</a></h1>
 <p>Lists are a lot like JavaScript arrays:</p>
 <blockquote>
@@ -475,6 +409,28 @@
 [1, 3]
 </pre>
 </blockquote>
+<p>It's also possible to index and slice lists and tuples, just like you
+can with strings:</p>
+<blockquote>
+<pre class="doctest-block">
+&gt;&gt;&gt; [&quot;hello&quot;, &quot;there&quot;, &quot;dude&quot;][-1]
+'dude'
+</pre>
+<pre class="doctest-block">
+&gt;&gt;&gt; [1, 2, 3][1:2]
+[2]
+</pre>
+</blockquote>
+<p>In fact, if the datatype is mutable like lists are, you can even
+<cite>assign</cite> to slices:</p>
+<blockquote>
+<pre class="doctest-block">
+&gt;&gt;&gt; a = [1, 2, 3, 4]
+&gt;&gt;&gt; a[1:3] = [5]
+&gt;&gt;&gt; a
+[1, 5, 4]
+</pre>
+</blockquote>
 </div>
 <div class="section">
 <h1><a id="control-flow" name="control-flow">Control Flow</a></h1>
@@ -513,41 +469,6 @@
 </blockquote>
 </div>
 <div class="section">
-<h1><a id="indexing-and-slicing" name="indexing-and-slicing">Indexing and Slicing</a></h1>
-<p>Any item that is a sequence can be indexed as expected, but unlike
-Javascript, negative indexes may be used to denote items from the end
-of the sequence:</p>
-<blockquote>
-<pre class="doctest-block">
-&gt;&gt;&gt; [&quot;hello&quot;, &quot;there&quot;, &quot;dude&quot;][-1]
-'dude'
-</pre>
-</blockquote>
-<p>Any indexable item can generally also be sliced; this is similar to
-<tt class="docutils literal"><span class="pre">String.slice</span></tt> in JavaScript, only built-in to the language:</p>
-<blockquote>
-<pre class="doctest-block">
-&gt;&gt;&gt; &quot;hello&quot;[2:4]     # Just like &quot;hello&quot;.slice(2,4) in JS
-'ll'
-&gt;&gt;&gt; &quot;hello&quot;[2:]      # Just like &quot;hello&quot;.slice(2) in JS
-'llo'
-&gt;&gt;&gt; &quot;hello&quot;[:4]      # Just like &quot;hello&quot;.slice(0,4) in JS
-'hell'
-&gt;&gt;&gt; [1, 2, 3][1:2]   # Works on lists, too!
-[2]
-</pre>
-</blockquote>
-<p>If the datatype is mutable, you can even assign to slices:</p>
-<blockquote>
-<pre class="doctest-block">
-&gt;&gt;&gt; a = [1, 2, 3, 4]
-&gt;&gt;&gt; a[1:3] = [5]
-&gt;&gt;&gt; a
-[1, 5, 4]
-</pre>
-</blockquote>
-</div>
-<div class="section">
 <h1><a id="dictionaries" name="dictionaries">Dictionaries</a></h1>
 <p>Dictionaries are a bit like Object literals in JavaScript:</p>
 <blockquote>
@@ -658,31 +579,7 @@
 <p>As you can see, classes in Python aren't particularly elegant; it's
 hard to understand exactly <cite>why</cite> things work the way they do unless
 you understand how classes are implemented &quot;under the hood&quot;, which is
-unfortunate. There are also some bumps in the history of Python's
-class mechanism: until version 2.2, Python's built-in types weren't
-part of the class heirarchy, and there was no root <tt class="docutils literal"><span class="pre">object</span></tt> class;
-these kinds of classes were known as <cite>old-style classes</cite>, and are
-being mentioned here solely because you may run across them when
-reading old code. They don't support a lot of the things that
-new-style classes do, and should be avoided if at all possible. You
-can tell that an object is an instance of an old-style or new-style
-class by using the <tt class="docutils literal"><span class="pre">type</span></tt> built-in function:</p>
-<blockquote>
-<pre class="doctest-block">
-&gt;&gt;&gt; class OldStyle:            # No superclass means it's old-style.
-...     pass
-&gt;&gt;&gt; class NewStyle(object):
-...     pass
-&gt;&gt;&gt; type(OldStyle())
-&lt;type 'instance'&gt;
-&gt;&gt;&gt; type(NewStyle())
-&lt;class 'NewStyle'&gt;
-</pre>
-</blockquote>
-<p>A number of the class mechanisms outlined in this tutorial don't work
-with old-style classes.  Fortunately, as with the string/unicode
-schism, this confusion will be resolved in Python 3000, which abandons
-old-style classes to their well-deserved fate.</p>
+unfortunate.</p>
 <p>Because classes in Python aren't really prototype-based, it's not easy
 to dynamically add or remove methods to existing objects
 on-the-fly--though some will probably tell you that doing such a thing
@@ -779,6 +676,41 @@
 </blockquote>
 </div>
 <div class="section">
+<h1><a id="closures" name="closures">Closures</a></h1>
+<p>Function closures are available in Python:</p>
+<blockquote>
+<pre class="doctest-block">
+&gt;&gt;&gt; def myfunc():
+...     a = 1
+...     def wrapped():
+...         return a
+...     return wrapped
+&gt;&gt;&gt; myfunc()()
+1
+</pre>
+</blockquote>
+<p>Unlike Javascript, however, the variable bindings in the closure are
+&quot;read-only&quot;:</p>
+<blockquote>
+<pre class="doctest-block">
+&gt;&gt;&gt; def myfunc():
+...     a = 1
+...     def wrapped():
+...         a += 1                 # Doesn't work!
+...         return a
+...     return wrapped
+&gt;&gt;&gt; myfunc()()
+Traceback (most recent call last):
+...
+UnboundLocalError: local variable 'a' referenced before assignment
+</pre>
+</blockquote>
+<p>This means that closures can't be used to access private variables
+like they can in JavaScript; instead, everything is visible, and
+implementation-specific variables are conventionally preceded with one
+or two underscores.</p>
+</div>
+<div class="section">
 <h1><a id="borrowed-goods" name="borrowed-goods">Borrowed Goods</a></h1>
 <p>As mentioned at the beginning of this document, some of JavaScript's
 latest features have been borrowed directly from Python.</p>
@@ -787,6 +719,99 @@
 1.7 <a class="reference" href="http://wiki.ecmascript.org/doku.php?id=proposals:iterators_and_generators">counterparts</a>.</p>
 </div>
 <div class="section">
+<h1><a id="caveats" name="caveats">Caveats</a></h1>
+<p>As with any language, there's a few wrinkles in Python's design and
+history that any newcomer should be aware of.  I'll try to outline the
+most important ones below.</p>
+<div class="section">
+<h2><a id="unicode" name="unicode">Unicode</a></h2>
+<p>Sometimes, strings are the bane of Python programming.  Unlike
+JavaScript, in which every string is unicode, strings in Python are
+really more like immutable arrays of bytes.  Unicode strings are an
+entirely different type, and unicode literals must be prepended with a
+<tt class="docutils literal"><span class="pre">u</span></tt>, like so:</p>
+<blockquote>
+<pre class="doctest-block">
+&gt;&gt;&gt; u&quot;I am a unicode string.&quot;
+u'I am a unicode string.'
+&gt;&gt;&gt; &quot;I am a non-unicode string.&quot;
+'I am a non-unicode string.'
+</pre>
+</blockquote>
+<p>The non-intuitiveness of this is due to historical reasons: Python is
+an older language than JavaScript and dates back to 1991, so the
+language didn't originally support unicode.  When support was added,
+it was added in a way that didn't break backwards compatibility.  This
+situation will be resolved in <a class="reference" href="http://www.python.org/dev/peps/pep-3000/">Python 3000</a>, the first version of
+Python to break backwards compatibility with previous versions.</p>
+<p>A string with a character encoding may be converted to a <tt class="docutils literal"><span class="pre">unicode</span></tt>
+object through the <tt class="docutils literal"><span class="pre">decode()</span></tt> method, like so:</p>
+<blockquote>
+<pre class="doctest-block">
+&gt;&gt;&gt; &quot;Here is an ellipsis: \xe2\x80\xa6&quot;.decode(&quot;utf-8&quot;)
+u'Here is an ellipsis: \u2026'
+</pre>
+</blockquote>
+<p>Conversely, you can convert a <tt class="docutils literal"><span class="pre">unicode</span></tt> object into a string via the
+<tt class="docutils literal"><span class="pre">encode()</span></tt> method:</p>
+<blockquote>
+<pre class="doctest-block">
+&gt;&gt;&gt; u&quot;Here is an ellipsis: \u2026&quot;.encode(&quot;utf-8&quot;)
+'Here is an ellipsis: \xe2\x80\xa6'
+</pre>
+</blockquote>
+<p>An exception will be raised if there are characters that aren't
+supported by the encoding you specify, though:</p>
+<blockquote>
+<pre class="doctest-block">
+&gt;&gt;&gt; u&quot;hello\u2026&quot;.encode(&quot;ascii&quot;)
+Traceback (most recent call last):
+...
+UnicodeEncodeError: 'ascii' codec can't encode character u'\u2026' in position 5: ordinal not in range(128)
+</pre>
+</blockquote>
+<p>As such, it's a good idea to optionally specify an algorithm to deal
+with characters that aren't supported by the encoding:</p>
+<blockquote>
+<pre class="doctest-block">
+&gt;&gt;&gt; u&quot;hello\u2026&quot;.encode(&quot;ascii&quot;, &quot;ignore&quot;)
+'hello'
+&gt;&gt;&gt; u&quot;hello\u2026&quot;.encode(&quot;ascii&quot;, &quot;xmlcharrefreplace&quot;)
+'hello&amp;#8230;'
+</pre>
+</blockquote>
+</div>
+<div class="section">
+<h2><a id="old-style-classes" name="old-style-classes">Old-Style Classes</a></h2>
+<p>There are also some bumps in the history of Python's
+class mechanism: until version 2.2, Python's built-in types weren't
+part of the class heirarchy, and there was no root <tt class="docutils literal"><span class="pre">object</span></tt> class;
+these kinds of classes were known as <cite>old-style classes</cite>, and are
+being mentioned here solely because you may run across them when
+reading old code. They don't support a lot of the things that
+new-style classes do, and should be avoided if at all possible. You
+can tell that an object is an instance of an old-style or new-style
+class by using the <tt class="docutils literal"><span class="pre">type</span></tt> built-in function:</p>
+<blockquote>
+<pre class="doctest-block">
+&gt;&gt;&gt; class OldStyle:            # No superclass means it's old-style.
+...     pass
+&gt;&gt;&gt; class NewStyle(object):
+...     pass
+&gt;&gt;&gt; type(OldStyle())
+&lt;type 'instance'&gt;
+&gt;&gt;&gt; type(NewStyle())
+&lt;class 'NewStyle'&gt;
+</pre>
+</blockquote>
+<p>A number of the class mechanisms outlined in this tutorial, such as
+the <tt class="docutils literal"><span class="pre">property()</span></tt> and <tt class="docutils literal"><span class="pre">super()</span></tt> built-in functions, don't work with
+old-style classes.  Fortunately, as with the string/unicode schism,
+this confusion will be resolved in Python 3000, which abandons
+old-style classes to their well-deserved fate.</p>
+</div>
+</div>
+<div class="section">
 <h1><a id="coding-style" name="coding-style">Coding Style</a></h1>
 <p>Python has a coding convention that's generally been embraced
 throughout the community; almost all libraries use it.  It's contained
--- a/PythonForJsProgrammers.txt	Fri Jun 06 12:54:07 2008 -0700
+++ b/PythonForJsProgrammers.txt	Fri Jun 06 13:15:22 2008 -0700
@@ -154,51 +154,26 @@
 Strings
 =======
 
-Strings are, unfortunately, the bane of Python programming.  Unlike
-JavaScript, in which every string is unicode, strings in Python are
-really more like immutable arrays of bytes.  Unicode strings are an
-entirely different type, and unicode literals must be prepended with a
-``u``, like so:
+Strings in Python work a lot like they do in JavaScript, but with some
+added benefits.
 
-    >>> u"I am a unicode string."
-    u'I am a unicode string.'
-    >>> "I am a non-unicode string."
-    'I am a non-unicode string.'
-
-The non-intuitiveness of this is due to historical reasons: Python is
-an older language than JavaScript and dates back to 1991, so the
-language didn't originally support unicode.  When support was added,
-it was added in a way that didn't break backwards compatibility.  This
-situation will be resolved in `Python 3000`_, the first version of
-Python to break backwards compatibility with previous versions.
-
-A string with a character encoding may be converted to a ``unicode``
-object through the ``decode()`` method, like so:
+Strings--or any sequence-like object in Python, for that matter--can
+be indexed by character like they can in JavaScript, with the addition
+that negative indexes may be used to denote items from the end of the
+sequence:
 
-    >>> "Here is an ellipsis: \xe2\x80\xa6".decode("utf-8")
-    u'Here is an ellipsis: \u2026'
-
-Conversely, you can convert a ``unicode`` object into a string via the
-``encode()`` method:
+    >>> "Hello"[-1]
+    'o'
 
-    >>> u"Here is an ellipsis: \u2026".encode("utf-8")
-    'Here is an ellipsis: \xe2\x80\xa6'
-
-An exception will be raised if there are characters that aren't
-supported by the encoding you specify, though:
+Any indexable item can generally also be sliced; this is similar to
+``String.slice`` in JavaScript, only built-in to the language:
 
-    >>> u"hello\u2026".encode("ascii")
-    Traceback (most recent call last):
-    ...
-    UnicodeEncodeError: 'ascii' codec can't encode character u'\u2026' in position 5: ordinal not in range(128)
-
-As such, it's a good idea to optionally specify an algorithm to deal
-with characters that aren't supported by the encoding:
-
-    >>> u"hello\u2026".encode("ascii", "ignore")
-    'hello'
-    >>> u"hello\u2026".encode("ascii", "xmlcharrefreplace")
-    'hello&#8230;'
+    >>> "hello"[2:4]     # Just like "hello".slice(2,4) in JS
+    'll'
+    >>> "hello"[2:]      # Just like "hello".slice(2) in JS
+    'llo'
+    >>> "hello"[:4]      # Just like "hello".slice(0,4) in JS
+    'hell'
 
 It's also easy to format strings in Python.  If you're familiar with
 C's ``sprintf()`` function, Python's string interpolation operator,
@@ -210,7 +185,6 @@
 You can find out more in the `String Formatting Operations`_ section
 of the Python Library Reference.
 
-.. _`Python 3000`: http://www.python.org/dev/peps/pep-3000/
 .. _`String Formatting Operations`: http://docs.python.org/lib/typesseq-strings.html
 
 Expressions
@@ -332,8 +306,8 @@
 
 .. _`arbitrary argument lists`: http://docs.python.org/tut/node6.html#SECTION006730000000000000000
 
-Global Variables
-================
+Variables
+=========
 
 Python, like JavaScript, is lexically scoped when it comes to reading
 variables.
@@ -362,38 +336,6 @@
 interpreter to assume that all new assignments are local unless
 explicitly told otherwise.
 
-Closures
-========
-
-Function closures are available in Python:
-
-    >>> def myfunc():
-    ...     a = 1
-    ...     def wrapped():
-    ...         return a
-    ...     return wrapped
-    >>> myfunc()()
-    1
-
-Unlike Javascript, however, the variable bindings in the closure are
-"read-only":
-
-    >>> def myfunc():
-    ...     a = 1
-    ...     def wrapped():
-    ...         a += 1                 # Doesn't work!
-    ...         return a
-    ...     return wrapped
-    >>> myfunc()()
-    Traceback (most recent call last):
-    ...
-    UnboundLocalError: local variable 'a' referenced before assignment
-
-This means that closures can't be used to access private variables
-like they can in JavaScript; instead, everything is visible, and
-implementation-specific variables are conventionally preceded with one
-or two underscores.
-
 Sequences
 =========
 
@@ -439,6 +381,23 @@
     >>> a
     [1, 3]
 
+It's also possible to index and slice lists and tuples, just like you
+can with strings:
+
+    >>> ["hello", "there", "dude"][-1]
+    'dude'
+
+    >>> [1, 2, 3][1:2]
+    [2]
+
+In fact, if the datatype is mutable like lists are, you can even
+`assign` to slices:
+
+    >>> a = [1, 2, 3, 4]
+    >>> a[1:3] = [5]
+    >>> a
+    [1, 5, 4]
+
 Control Flow
 ============
 
@@ -470,35 +429,6 @@
     1
     2
 
-Indexing and Slicing
-====================
-
-Any item that is a sequence can be indexed as expected, but unlike
-Javascript, negative indexes may be used to denote items from the end
-of the sequence:
-
-    >>> ["hello", "there", "dude"][-1]
-    'dude'
-
-Any indexable item can generally also be sliced; this is similar to
-``String.slice`` in JavaScript, only built-in to the language:
-
-    >>> "hello"[2:4]     # Just like "hello".slice(2,4) in JS
-    'll'
-    >>> "hello"[2:]      # Just like "hello".slice(2) in JS
-    'llo'
-    >>> "hello"[:4]      # Just like "hello".slice(0,4) in JS
-    'hell'
-    >>> [1, 2, 3][1:2]   # Works on lists, too!
-    [2]
-
-If the datatype is mutable, you can even assign to slices:
-
-    >>> a = [1, 2, 3, 4]
-    >>> a[1:3] = [5]
-    >>> a
-    [1, 5, 4]
-
 Dictionaries
 ============
 
@@ -594,29 +524,7 @@
 As you can see, classes in Python aren't particularly elegant; it's
 hard to understand exactly `why` things work the way they do unless
 you understand how classes are implemented "under the hood", which is
-unfortunate. There are also some bumps in the history of Python's
-class mechanism: until version 2.2, Python's built-in types weren't
-part of the class heirarchy, and there was no root ``object`` class;
-these kinds of classes were known as `old-style classes`, and are
-being mentioned here solely because you may run across them when
-reading old code. They don't support a lot of the things that
-new-style classes do, and should be avoided if at all possible. You
-can tell that an object is an instance of an old-style or new-style
-class by using the ``type`` built-in function:
-
-    >>> class OldStyle:            # No superclass means it's old-style.
-    ...     pass
-    >>> class NewStyle(object):
-    ...     pass
-    >>> type(OldStyle())
-    <type 'instance'>
-    >>> type(NewStyle())
-    <class 'NewStyle'>
-
-A number of the class mechanisms outlined in this tutorial don't work
-with old-style classes.  Fortunately, as with the string/unicode
-schism, this confusion will be resolved in Python 3000, which abandons
-old-style classes to their well-deserved fate.
+unfortunate.
 
 Because classes in Python aren't really prototype-based, it's not easy
 to dynamically add or remove methods to existing objects
@@ -709,6 +617,38 @@
 
 .. _`built-in ones`: http://docs.python.org/lib/module-exceptions.html
 
+Closures
+========
+
+Function closures are available in Python:
+
+    >>> def myfunc():
+    ...     a = 1
+    ...     def wrapped():
+    ...         return a
+    ...     return wrapped
+    >>> myfunc()()
+    1
+
+Unlike Javascript, however, the variable bindings in the closure are
+"read-only":
+
+    >>> def myfunc():
+    ...     a = 1
+    ...     def wrapped():
+    ...         a += 1                 # Doesn't work!
+    ...         return a
+    ...     return wrapped
+    >>> myfunc()()
+    Traceback (most recent call last):
+    ...
+    UnboundLocalError: local variable 'a' referenced before assignment
+
+This means that closures can't be used to access private variables
+like they can in JavaScript; instead, everything is visible, and
+implementation-specific variables are conventionally preceded with one
+or two underscores.
+
 Borrowed Goods
 ==============
 
@@ -725,6 +665,92 @@
 .. _`list comprehensions`: http://docs.python.org/tut/node7.html#SECTION007140000000000000000
 .. _`counterparts`: http://wiki.ecmascript.org/doku.php?id=proposals:iterators_and_generators
 
+Caveats
+=======
+
+As with any language, there's a few wrinkles in Python's design and
+history that any newcomer should be aware of.  I'll try to outline the
+most important ones below.
+
+Unicode
+-------
+
+Sometimes, strings are the bane of Python programming.  Unlike
+JavaScript, in which every string is unicode, strings in Python are
+really more like immutable arrays of bytes.  Unicode strings are an
+entirely different type, and unicode literals must be prepended with a
+``u``, like so:
+
+    >>> u"I am a unicode string."
+    u'I am a unicode string.'
+    >>> "I am a non-unicode string."
+    'I am a non-unicode string.'
+
+The non-intuitiveness of this is due to historical reasons: Python is
+an older language than JavaScript and dates back to 1991, so the
+language didn't originally support unicode.  When support was added,
+it was added in a way that didn't break backwards compatibility.  This
+situation will be resolved in `Python 3000`_, the first version of
+Python to break backwards compatibility with previous versions.
+
+A string with a character encoding may be converted to a ``unicode``
+object through the ``decode()`` method, like so:
+
+    >>> "Here is an ellipsis: \xe2\x80\xa6".decode("utf-8")
+    u'Here is an ellipsis: \u2026'
+
+Conversely, you can convert a ``unicode`` object into a string via the
+``encode()`` method:
+
+    >>> u"Here is an ellipsis: \u2026".encode("utf-8")
+    'Here is an ellipsis: \xe2\x80\xa6'
+
+An exception will be raised if there are characters that aren't
+supported by the encoding you specify, though:
+
+    >>> u"hello\u2026".encode("ascii")
+    Traceback (most recent call last):
+    ...
+    UnicodeEncodeError: 'ascii' codec can't encode character u'\u2026' in position 5: ordinal not in range(128)
+
+As such, it's a good idea to optionally specify an algorithm to deal
+with characters that aren't supported by the encoding:
+
+    >>> u"hello\u2026".encode("ascii", "ignore")
+    'hello'
+    >>> u"hello\u2026".encode("ascii", "xmlcharrefreplace")
+    'hello&#8230;'
+
+.. _`Python 3000`: http://www.python.org/dev/peps/pep-3000/
+
+Old-Style Classes
+-----------------
+
+There are also some bumps in the history of Python's
+class mechanism: until version 2.2, Python's built-in types weren't
+part of the class heirarchy, and there was no root ``object`` class;
+these kinds of classes were known as `old-style classes`, and are
+being mentioned here solely because you may run across them when
+reading old code. They don't support a lot of the things that
+new-style classes do, and should be avoided if at all possible. You
+can tell that an object is an instance of an old-style or new-style
+class by using the ``type`` built-in function:
+
+    >>> class OldStyle:            # No superclass means it's old-style.
+    ...     pass
+    >>> class NewStyle(object):
+    ...     pass
+    >>> type(OldStyle())
+    <type 'instance'>
+    >>> type(NewStyle())
+    <class 'NewStyle'>
+
+A number of the class mechanisms outlined in this tutorial, such as
+the ``property()`` and ``super()`` built-in functions, don't work with
+old-style classes.  Fortunately, as with the string/unicode schism,
+this confusion will be resolved in Python 3000, which abandons
+old-style classes to their well-deserved fate.
+
 Coding Style
 ============