From f8185b7dfb08d0a969ea77263a8d0535ca8f0d98 Mon Sep 17 00:00:00 2001 From: Mark Pilgrim Date: Thu, 23 Apr 2009 11:06:51 -0400 Subject: [PATCH] dropped /td, /th, /tr end elements --- porting-code-to-python-3-with-2to3.html | 1320 +++++++++++------------ your-first-python-program.html | 6 +- 2 files changed, 663 insertions(+), 663 deletions(-) diff --git a/porting-code-to-python-3-with-2to3.html b/porting-code-to-python-3-with-2to3.html index d979d71..fb1cdcf 100644 --- a/porting-code-to-python-3-with-2to3.html +++ b/porting-code-to-python-3-with-2to3.html @@ -32,25 +32,25 @@ td pre{padding:0;border:0}

In Python 2, print was a statement. Whatever you wanted to print simply followed the print keyword. In Python 3, print() is a function — whatever you want to print is passed to print() like any other function. - - - - - - - - - - - - - - - - - - - +
NotesPython 2Python 3
printprint()
print 1print(1)
print 1, 2print(1, 2)
print 1, 2,print(1, 2, end=' ')
print >>sys.stderr, 1, 2, 3print(1, 2, 3, file=sys.stderr)
Notes +Python 2 +Python 3 + +
① +print +print() +
② +print 1 +print(1) +
③ +print 1, 2 +print(1, 2) +
④ +print 1, 2, +print(1, 2, end=' ') +
⑤ +print >>sys.stderr, 1, 2, 3 +print(1, 2, 3, file=sys.stderr)

  1. To print a blank line, call print() without any arguments. @@ -62,16 +62,16 @@ td pre{padding:0;border:0}

    Unicode string literals

    Python 2 had two string types: Unicode strings and non-Unicode strings. Python 3 has one string type: Unicode strings. - - - - - - - - - - +
    NotesPython 2Python 3
    u"PapayaWhip""PapayaWhip"
    ur"PapayaWhip\foo"r"PapayaWhip\foo"
    Notes +Python 2 +Python 3 + +
    ① +u"PapayaWhip" +"PapayaWhip" +
    ② +ur"PapayaWhip\foo" +r"PapayaWhip\foo"

    1. Unicode string literals are simply converted into string literals, which, in Python 3, are always Unicode. @@ -80,37 +80,37 @@ td pre{padding:0;border:0}

      unicode() global function

      Python 2 had two global functions to coerce objects into strings: unicode() to coerce them into Unicode strings, and str() to coerce them into non-Unicode strings. Python 3 has only one string type, Unicode strings, so the str() function is all you need. (The unicode() function no longer exists.) - - - - - - - +
      NotesPython 2Python 3
      unicode(anything)str(anything)
      Notes +Python 2 +Python 3 + +
      +unicode(anything) +str(anything)

      long data type

      Python 2 had separate int and long types for non-floating-point numbers. An int could not be any larger than sys.maxint, which varied by platform. Longs were defined by appending an L to the end of the number, and they could be, well, longer than ints. In Python 3, there is only one integer type, called int, which mostly behaves like the long type in Python 2. Since there are no longer two types, there is no need for special syntax to distinguish them.

      Further reading: PEP 237: Unifying Long Integers and Integers. - - - - - - - - - - - - - - - - - - - +
      NotesPython 2Python 3
      x = 1000000000000Lx = 1000000000000
      x = 0xFFFFFFFFFFFFLx = 0xFFFFFFFFFFFF
      long(x)int(x)
      type(x) is longtype(x) is int
      isinstance(x, long)isinstance(x, int)
      Notes +Python 2 +Python 3 + +
      ① +x = 1000000000000L +x = 1000000000000 +
      ② +x = 0xFFFFFFFFFFFFL +x = 0xFFFFFFFFFFFF +
      ③ +long(x) +int(x) +
      ④ +type(x) is long +type(x) is int +
      ⑤ +isinstance(x, long) +isinstance(x, int)

      1. Base 10 long integer literals become base 10 integer literals. @@ -122,16 +122,16 @@ td pre{padding:0;border:0}

        <> comparison

        Python 2 supported <> as a synonym for !=, the not-equals comparison operator. Python 3 supports the != operator, but not <>. - - - - - - - - - - +
        NotesPython 2Python 3
        if x <> y:if x != y:
        if x <> y <> z:if x != y != z:
        Notes +Python 2 +Python 3 + +
        ① +if x <> y: +if x != y: +
        ② +if x <> y <> z: +if x != y != z:

        1. A simple comparison. @@ -140,25 +140,25 @@ td pre{padding:0;border:0}

          has_key() dictionary method

          In Python 2, dictionaries had a has_key() method to test whether the dictionary had a certain key. In Python 3, this method no longer exists. Instead, you need to use the in operator. - - - - - - - + - - - - - - - - - - - +
          NotesPython 2Python 3
          a_dictionary.has_key("PapayaWhip")"PapayaWhip" in a_dictionary
          Notes +Python 2 +Python 3 + +
          ① +a_dictionary.has_key("PapayaWhip") +"PapayaWhip" in a_dictionary
          a_dictionary.has_key(x) or a_dictionary.has_key(y)x in a_dictionary or y in a_dictionary
          a_dictionary.has_key(x or y)(x or y) in a_dictionary
          a_dictionary.has_key(x + y)(x + y) in a_dictionary
          x + a_dictionary.has_key(y)x + (y in a_dictionary)
          a_dictionary.has_key(x) or a_dictionary.has_key(y) +x in a_dictionary or y in a_dictionary +
          ③ +a_dictionary.has_key(x or y) +(x or y) in a_dictionary +
          ④ +a_dictionary.has_key(x + y) +(x + y) in a_dictionary +
          ⑤ +x + a_dictionary.has_key(y) +x + (y in a_dictionary)

          1. The simplest form. @@ -170,25 +170,25 @@ td pre{padding:0;border:0}

            Dictionary methods that return lists

            In Python 2, many dictionary methods returned lists. The most frequently used methods were keys(), items(), and values(). In Python 3, all of these methods return dynamic views. In some contexts, this is not a problem. If the method's return value is immediately passed to another function that iterates through the entire sequence, it makes no difference whether the actual type is a list or a view. In other contexts, it matters a great deal. If you were expecting a complete list with individually addressable elements, your code will choke, because views do not support indexing. - - - - - - - - - - - - - - - - - - - +
            NotesPython 2Python 3
            a_dictionary.keys()list(a_dictionary.keys())
            a_dictionary.items()list(a_dictionary.items())
            a_dictionary.iterkeys()iter(a_dictionary.keys())
            [i for i in a_dictionary.iterkeys()][i for i in a_dictionary.keys()]
            min(a_dictionary.keys())no change
            Notes +Python 2 +Python 3 + +
            ① +a_dictionary.keys() +list(a_dictionary.keys()) +
            ② +a_dictionary.items() +list(a_dictionary.items()) +
            ③ +a_dictionary.iterkeys() +iter(a_dictionary.keys()) +
            ④ +[i for i in a_dictionary.iterkeys()] +[i for i in a_dictionary.keys()] +
            ⑤ +min(a_dictionary.keys()) +no change

            1. 2to3 errs on the side of safety, converting the return value from keys() to a static list with the list() function. This will always work, but it will be less efficient than using a view. You should examine the converted code to see if a list is absolutely necessary, or if a view would do. @@ -202,24 +202,24 @@ td pre{padding:0;border:0}

              http

              In Python 3, several related HTTP modules have been combined into a single package, http. - - - - - - - - - - - - - - + - +import CGIHttpServer +
              NotesPython 2Python 3
              import httplibimport http.client
              import Cookieimport http.cookies
              import cookielibimport http.cookiejar
              Notes +Python 2 +Python 3 + +
              ① +import httplib +import http.client +
              ② +import Cookie +import http.cookies +
              ③ +import cookielib +import http.cookiejar +
              import BaseHTTPServer
               import SimpleHTTPServer
              -import CGIHttpServer
              import http.server
              import http.server

              1. The http.client module implements a low-level library that can request HTTP resources and interpret HTTP responses. @@ -230,32 +230,32 @@ import CGIHttpServer

                urllib

                Python 2 had a rat's nest of overlapping modules to parse, encode, and fetch URLs. In Python 3, these have all been refactored and combined in a single package, urllib. - - - - - - - - - - - - - - - - - + +from urllib import urlencode - +from urllib.parse import urlencode + +from urllib2 import HTTPError +from urllib.error import HTTPError
                NotesPython 2Python 3
                import urllibimport urllib.request, urllib.parse, urllib.error
                import urllib2import urllib.request, urllib.error
                import urlparseimport urllib.parse
                import robotparserimport urllib.robotparser
                Notes +Python 2 +Python 3 + +
                ① +import urllib +import urllib.request, urllib.parse, urllib.error +
                ② +import urllib2 +import urllib.request, urllib.error +
                ③ +import urlparse +import urllib.parse +
                ④ +import robotparser +import urllib.robotparser +
                from urllib import FancyURLopener
                -from urllib import urlencode
                from urllib.request import FancyURLopener
                -from urllib.parse import urlencode
                from urllib2 import Request
                -from urllib2 import HTTPError
                from urllib.request import Request
                -from urllib.error import HTTPError

                1. The old urllib module in Python 2 had a variety of functions, including urlopen() for fetching data and splittype(), splithost(), and splituser() for splitting a URL into its constituent parts. These functions have been reorganized more logically within the new urllib package. 2to3 will also change all calls to these functions so they use the new naming scheme. @@ -268,81 +268,81 @@ from urllib.error import HTTPError

                  dbm

                  All the various DBM clones are now in a single package, dbm. If you need a specific variant like GNU DBM, you can import the appropriate module within the dbm package. - - - - - - - - - - - - - - - - - + - +import whichdb +
                  NotesPython 2Python 3
                  import dbmimport dbm.ndbm
                  import gdbmimport dbm.gnu
                  import dbhashimport dbm.bsd
                  import dumbdbmimport dbm.dumb
                  Notes +Python 2 +Python 3 + +
                  +import dbm +import dbm.ndbm +
                  +import gdbm +import dbm.gnu +
                  +import dbhash +import dbm.bsd +
                  +import dumbdbm +import dbm.dumb +
                  import anydbm
                  -import whichdb
                  import dbm
                  import dbm

                  xmlrpc

                  XML-RPC is a lightweight method of performing remote RPC calls over HTTP. The XML-RPC client library and several XML-RPC server implementations are now combined in a single package, xmlrpc. - - - - - - - - + - +import SimpleXMLRPCServer +
                  NotesPython 2Python 3
                  import xmlrpclibimport xmlrpc.client
                  Notes +Python 2 +Python 3 + +
                  +import xmlrpclib +import xmlrpc.client +
                  import DocXMLRPCServer
                  -import SimpleXMLRPCServer
                  import xmlrpc.server
                  import xmlrpc.server

                  Other modules

                  - - - - - + - - + import StringIO + - - - - - - - - - - - - - - - - - - - - - - + import pickle +
                  NotesPython 2Python 3
                  Notes +Python 2 +Python 3 + +
                  try:
                       import cStringIO as StringIO
                   except ImportError:
                  -    import StringIO
                  import io
                  import io +
                  try:
                       import cPickle as pickle
                   except ImportError:
                  -    import pickle
                  import pickle
                  import __builtin__import builtins
                  import copy_regimport copyreg
                  import Queueimport queue
                  import SocketServerimport socketserver
                  import ConfigParserimport configparser
                  import reprimport reprlib
                  import commandsimport subprocess
                  import pickle +
                  ③ +import __builtin__ +import builtins +
                  ④ +import copy_reg +import copyreg +
                  ⑤ +import Queue +import queue +
                  ⑥ +import SocketServer +import socketserver +
                  ⑦ +import ConfigParser +import configparser +
                  ⑧ +import repr +import reprlib +
                  ⑨ +import commands +import subprocess
                  1. A common idiom in Python 2 was to try to import cStringIO as StringIO, and if that failed, to import StringIO instead. Do not do this in Python 3; the io module does it for you. It will find the fastest implementation available and use it automatically. @@ -369,16 +369,16 @@ except ImportError: +--universaldetector.py

                    Now suppose that universaldetector.py needs to import the entire constants.py file and one class from mbcharsetprober.py. How do you do it? - - - - - - - - - - +
                    NotesPython 2Python 3
                    import constantsfrom . import constants
                    from mbcharsetprober import MultiByteCharSetProberfrom .mbcharsetprober import MultiByteCharsetProber
                    Notes +Python 2 +Python 3 + +
                    ① +import constants +from . import constants +
                    ② +from mbcharsetprober import MultiByteCharSetProber +from .mbcharsetprober import MultiByteCharsetProber

                    1. When you need to import an entire module from elsewhere in your package, use the new from . import syntax. The period is actually a relative path from this file (universaldetector.py) to the file you want to import (constants.py). In this case, they are in the same directory, thus the single period. You can also import from the parent directory (from .. import anothermodule) or a subdirectory. @@ -387,35 +387,35 @@ except ImportError:

                      next() iterator method

                      In Python 2, iterators had a next() method which returned the next item in the sequence. That's still true in Python 3, but there is now also a global next() function that takes an iterator as an argument. - - - - - - - - - - - + + pass - + pass + - - + pass + + an_iterator.next() + an_iterator.__next__()
                      NotesPython 2Python 3
                      anIterator.next()next(anIterator)
                      a_function_that_returns_an_iterator().next()next(a_function_that_returns_an_iterator())
                      Notes +Python 2 +Python 3 + +
                      ① +anIterator.next() +next(anIterator) +
                      ② +a_function_that_returns_an_iterator().next() +next(a_function_that_returns_an_iterator()) +
                      class A:
                           def next(self):
                      -        pass
                      class A:
                           def __next__(self):
                      -        pass
                      class A:
                           def next(self, x, y):
                      -        pass
                      no change
                      no change +
                      next = 42
                       for an_iterator in a_sequence_of_iterators:
                      -    an_iterator.next()
                      next = 42
                       for an_iterator in a_sequence_of_iterators:
                      -    an_iterator.__next__()

                      1. In the simplest case, instead of calling an iterator's next() method, you now pass the iterator itself to the global next() function. @@ -427,25 +427,25 @@ for an_iterator in a_sequence_of_iterators:

                        filter() global function

                        In Python 2, the filter() function returned a list, the result of filtering a sequence through a function that returned True or False for each item in the sequence. In Python 3, the filter() function returns an iterator, not a list. - - - - - - - - - - - - - - - - - - - +
                        NotesPython 2Python 3
                        filter(a_function, a_sequence)list(filter(a_function, a_sequence))
                        list(filter(a_function, a_sequence))no change
                        filter(None, a_sequence)[i for i in a_sequence if i]
                        for i in filter(None, a_sequence):no change
                        [i for i in filter(a_function, a_sequence)]no change
                        Notes +Python 2 +Python 3 + +
                        ① +filter(a_function, a_sequence) +list(filter(a_function, a_sequence)) +
                        ② +list(filter(a_function, a_sequence)) +no change +
                        ③ +filter(None, a_sequence) +[i for i in a_sequence if i] +
                        ④ +for i in filter(None, a_sequence): +no change +
                        ⑤ +[i for i in filter(a_function, a_sequence)] +no change

                        1. In the most basic case, 2to3 will wrap a call to filter() with a call to list(), which simply iterates through its argument and returns a real list. @@ -457,25 +457,25 @@ for an_iterator in a_sequence_of_iterators:

                          map() global function

                          In much the same way as filter(), the map() function now returns an iterator. (In Python 2, it returned a list.) - - - - - - - - - - - - - - - - - - - +
                          NotesPython 2Python 3
                          map(a_function, 'PapayaWhip')list(map(a_function, 'PapayaWhip'))
                          map(None, 'PapayaWhip')list('PapayaWhip')
                          map(lambda x: x+1, range(42))[x+1 for x in range(42)]
                          for i in map(a_function, a_sequence):no change
                          [i for i in map(a_function, a_sequence)]no change
                          Notes +Python 2 +Python 3 + +
                          ① +map(a_function, 'PapayaWhip') +list(map(a_function, 'PapayaWhip')) +
                          ② +map(None, 'PapayaWhip') +list('PapayaWhip') +
                          ③ +map(lambda x: x+1, range(42)) +[x+1 for x in range(42)] +
                          ④ +for i in map(a_function, a_sequence): +no change +
                          ⑤ +[i for i in map(a_function, a_sequence)] +no change

                          1. As with filter(), in the most basic case, 2to3 will wrap a call to map() with a call to list(). @@ -487,14 +487,14 @@ for an_iterator in a_sequence_of_iterators:

                            reduce() global function (3.1+)

                            In Python 3, the reduce() function has been removed from the global namespace and placed in the functools module. - - - - - - + +reduce(a, b, c)
                            NotesPython 2Python 3
                            reduce(a, b, c)
                            Notes +Python 2 +Python 3 + +
                            +reduce(a, b, c)
                            from functtools import reduce
                            -reduce(a, b, c)

                            The version of 2to3 that shipped with Python 3.0 would not fix the reduce() function automatically. The fix first appeared in the 2to3 script that shipped with Python 3.1. @@ -502,22 +502,22 @@ reduce(a, b, c)

                            apply() global function

                            Python 2 had a global function called apply(), which took a function f and a list [a, b, c] and returned f(a, b, c). In Python 3, the apply() function no longer exists. Instead, there is a new function calling syntax that allows you to pass a list and have Python apply the list as the function's arguments. - - - - - - - - - - - - - - - - +
                            NotesPython 2Python 3
                            apply(a_function, a_list_of_args)a_function(*a_list_of_args)
                            apply(a_function, a_list_of_args, a_dictionary_of_named_args)a_function(*a_list_of_args, **a_dictionary_of_named_args)
                            apply(a_function, a_list_of_args + z)a_function(*a_list_of_args + z)
                            apply(aModule.a_function, a_list_of_args)aModule.a_function(*a_list_of_args)
                            Notes +Python 2 +Python 3 + +
                            ① +apply(a_function, a_list_of_args) +a_function(*a_list_of_args) +
                            ② +apply(a_function, a_list_of_args, a_dictionary_of_named_args) +a_function(*a_list_of_args, **a_dictionary_of_named_args) +
                            ③ +apply(a_function, a_list_of_args + z) +a_function(*a_list_of_args + z) +
                            ④ +apply(aModule.a_function, a_list_of_args) +aModule.a_function(*a_list_of_args)

                            1. In the simplest form, you can call a function with a list of arguments (an actual list like [a, b, c]) by prepending the list with an asterisk (*). This is exactly equivalent to the old apply() function in Python 2. @@ -528,30 +528,30 @@ reduce(a, b, c)

                              intern() global function

                              In Python 2, you could call the intern() function on a string to intern it as a performance optimization. In Python 3, the intern() function has been moved to the sys module. - - - - - - - +
                              NotesPython 2Python 3
                              intern(aString)sys.intern(aString)
                              Notes +Python 2 +Python 3 + +
                              +intern(aString) +sys.intern(aString)

                              exec statement

                              Just as the print statement became a function in Python 3, so too has the exec statement. The exec() function takes a string which contains arbitrary Python code and executes it as if it were just another statement or expression. - - - - - - - - - - - - - +
                              NotesPython 2Python 3
                              exec codeStringexec(codeString)
                              exec codeString in a_global_namespaceexec(codeString, a_global_namespace)
                              exec codeString in a_global_namespace, a_local_namespaceexec(codeString, a_global_namespace, a_local_namespace)
                              Notes +Python 2 +Python 3 + +
                              ① +exec codeString +exec(codeString) +
                              ② +exec codeString in a_global_namespace +exec(codeString, a_global_namespace) +
                              ③ +exec codeString in a_global_namespace, a_local_namespace +exec(codeString, a_global_namespace, a_local_namespace)

                              1. In the simplest form, the 2to3 script simply encloses the code-as-a-string in parentheses, since exec() is now a function instead of a statement. @@ -561,13 +561,13 @@ reduce(a, b, c)

                                execfile statement (3.1+)

                                Like the old exec statement, the old execfile statement will execute strings as if they were Python code. Where exec took a string, execfile took a filename. In Python 3, the execfile statement has been eliminated. If you really need to take a file of Python code and execute it (but you're not willing to simply import it), you can accomplish the same thing by opening the file, reading its contents, calling the global compile() function to force the Python interpreter to compile the code, and then call the new exec() function. - - - - - - - +
                                NotesPython 2Python 3
                                execfile("a_filename")exec(compile(open("a_filename").read(), "a_filename", "exec"))
                                Notes +Python 2 +Python 3 + +
                                +execfile("a_filename") +exec(compile(open("a_filename").read(), "a_filename", "exec"))

                                The version of 2to3 that shipped with Python 3.0 would not fix the execfile statement automatically. The fix first appeared in the 2to3 script that shipped with Python 3.1. @@ -575,16 +575,16 @@ reduce(a, b, c)

                                repr literals (backticks)

                                In Python 2, there was a special syntax of wrapping any object in backticks (like `x`) to get a representation of the object. In Python 3, this capability still exists, but you can no longer use backticks to get it. Instead, use the global repr() function. - - - - - - - - - - +
                                NotesPython 2Python 3
                                `x`repr(x)
                                `"PapayaWhip" + `2``repr("PapayaWhip" + repr(2))
                                Notes +Python 2 +Python 3 + +
                                ① +`x` +repr(x) +
                                ② +`"PapayaWhip" + `2`` +repr("PapayaWhip" + repr(2))

                                1. Remember, x can be anything — a class, a function, a module, a primitive data type, etc. The repr() function works on everything. @@ -593,40 +593,40 @@ reduce(a, b, c)

                                  try...except statement

                                  The syntax for catching exceptions has changed slightly between Python 2 and Python 3. - - - - - + + pass - + pass + + pass - + pass + - - + pass + - + pass +
                                  NotesPython 2Python 3
                                  Notes +Python 2 +Python 3 + +
                                  try:
                                       import mymodule
                                   except ImportError, e
                                  -    pass
                                  try:
                                       import mymodule
                                   except ImportError as e:
                                  -    pass
                                  try:
                                       import mymodule
                                   except (RuntimeError, ImportError), e
                                  -    pass
                                  try:
                                       import mymodule
                                   except (RuntimeError, ImportError) as e:
                                  -    pass
                                  try:
                                       import mymodule
                                   except ImportError:
                                  -    pass
                                  no change
                                  no change +
                                  try:
                                       import mymodule
                                   except:
                                  -    pass
                                  no change
                                  no change

                                  1. Instead of a comma after the exception type, Python 3 uses a new keyword, as. @@ -640,22 +640,22 @@ except:

                                    raise statement

                                    The syntax for raising your own exceptions has changed slightly between Python 2 and Python 3. - - - - - - - - - - - - - - - - +
                                    NotesPython 2Python 3
                                    raise MyExceptionunchanged
                                    raise MyException, "error message"raise MyException("error message")
                                    raise MyException, "error message", a_tracebackraise MyException("error message").with_traceback(a_traceback)
                                    raise "error message"unsupported
                                    Notes +Python 2 +Python 3 + +
                                    ① +raise MyException +unchanged +
                                    ② +raise MyException, "error message" +raise MyException("error message") +
                                    ③ +raise MyException, "error message", a_traceback +raise MyException("error message").with_traceback(a_traceback) +
                                    ④ +raise "error message" +unsupported

                                    1. In the simplest form, raising an exception without a custom error message, the syntax is unchanged. @@ -666,19 +666,19 @@ except:

                                      throw method on generators

                                      In Python 2, generators have a throw() method. Calling a_generator.throw() raises an exception at the point where the generator was paused, then returns the next value yielded by the generator function. In Python 3, this functionality is still available, but the syntax is slightly different. - - - - - - - - - - - - - +
                                      NotesPython 2Python 3
                                      a_generator.throw(MyException)no change
                                      a_generator.throw(MyException, "error message")a_generator.throw(MyException("error message"))
                                      a_generator.throw("error message")unsupported
                                      Notes +Python 2 +Python 3 + +
                                      ① +a_generator.throw(MyException) +no change +
                                      ② +a_generator.throw(MyException, "error message") +a_generator.throw(MyException("error message")) +
                                      ③ +a_generator.throw("error message") +unsupported

                                      1. In the simplest form, a generator throws an exception without a custom error message. In this case, the syntax has not changed between Python 2 and Python 3. @@ -688,25 +688,25 @@ except:

                                        xrange() global function

                                        In Python 2, there were two ways to get a range of numbers: range(), which returned a list, and xrange(), which returned an iterator. In Python 3, range() returns an iterator, and xrange() doesn't exist. - - - - - - - - - - - - - - - - - - - +
                                        NotesPython 2Python 3
                                        xrange(10)range(10)
                                        a_list = range(10)a_list = list(range(10))
                                        [i for i in xrange(10)][i for i in range(10)]
                                        for i in range(10):no change
                                        sum(range(10))no change
                                        Notes +Python 2 +Python 3 + +
                                        ① +xrange(10) +range(10) +
                                        ② +a_list = range(10) +a_list = list(range(10)) +
                                        ③ +[i for i in xrange(10)] +[i for i in range(10)] +
                                        ④ +for i in range(10): +no change +
                                        ⑤ +sum(range(10)) +no change

                                        1. In the simplest case, the 2to3 script will simply convert xrange() to range(). @@ -718,19 +718,19 @@ except:

                                          raw_input() and input() global functions

                                          Python 2 had two global functions for asking the user for input on the command line. The first, called input(), expected the user to enter a Python expression (and returned the result). The second, called raw_input(), just returned whatever the user typed. This was wildly confusing for beginners and widely regarded as a “wart” in the language. Python 3 excises this wart by renaming raw_input() to input(), so it works the way everyone naively expects it to work. - - - - - - - - - - - - - +
                                          NotesPython 2Python 3
                                          raw_input()input()
                                          raw_input("prompt")input("prompt")
                                          input()eval(input())
                                          Notes +Python 2 +Python 3 + +
                                          ① +raw_input() +input() +
                                          ② +raw_input("prompt") +input("prompt") +
                                          ③ +input() +eval(input())

                                          1. In the simplest form, raw_input() becomes input(). @@ -740,31 +740,31 @@ except:

                                            func_* function attributes

                                            In Python 2, code within functions can access special attributes about the function itself. In Python 3, these special function attributes have been renamed for consistency with other attributes. - - - - - - - - - - - - - - - - - - - - - - - - - +
                                            NotesPython 2Python 3
                                            a_function.func_namea_function.__name__
                                            a_function.func_doca_function.__doc__
                                            a_function.func_defaultsa_function.__defaults__
                                            a_function.func_dicta_function.__dict__
                                            a_function.func_closurea_function.__closure__
                                            a_function.func_globalsa_function.__globals__
                                            a_function.func_codea_function.__code__
                                            Notes +Python 2 +Python 3 + +
                                            ① +a_function.func_name +a_function.__name__ +
                                            ② +a_function.func_doc +a_function.__doc__ +
                                            ③ +a_function.func_defaults +a_function.__defaults__ +
                                            ④ +a_function.func_dict +a_function.__dict__ +
                                            ⑤ +a_function.func_closure +a_function.__closure__ +
                                            ⑥ +a_function.func_globals +a_function.__globals__ +
                                            ⑦ +a_function.func_code +a_function.__code__

                                            1. The __name__ attribute (previously func_name) contains the function's name. @@ -778,16 +778,16 @@ except:

                                              xreadlines() I/O method

                                              In Python 2, file objects had an xreadlines() method which returned an iterator that would read the file one line at a time. This was useful in for loops, among other places. In fact, it was so useful, later versions of Python 2 added the capability to file objects themselves. - - - - - - - - - - +
                                              NotesPython 2Python 3
                                              for line in a_file.xreadlines():for line in a_file:
                                              for line in a_file.xreadlines(5):no change
                                              Notes +Python 2 +Python 3 + +
                                              ① +for line in a_file.xreadlines(): +for line in a_file: +
                                              ② +for line in a_file.xreadlines(5): +no change

                                              1. If you used to call xreadlines() with no arguments, 2to3 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 for loop. @@ -797,22 +797,22 @@ except:

                                                lambda functions that take a tuple instead of multiple parameters

                                                In Python 2, you could define anonymous lambda functions which took multiple parameters by defining the function as taking a tuple with a specific number of items. In effect, Python 2 would “unpack” the tuple into named arguments, which you could then reference (by name) within the lambda function. In Python 3, you can still pass a tuple to a lambda 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. - - - - - - - - - - - - - - - - +
                                                NotesPython 2Python 3
                                                lambda (x,): x + f(x)lambda x1: x1[0] + f(x1[0])
                                                lambda (x, y): x + f(y)lambda x_y: x_y[0] + f(x_y[1])
                                                lambda (x, (y, z)): x + y + zlambda x_y_z: x_y_z[0] + x_y_z[1][0] + x_y_z[1][1]
                                                lambda x, y, z: x + y + zunchanged
                                                Notes +Python 2 +Python 3 + +
                                                ① +lambda (x,): x + f(x) +lambda x1: x1[0] + f(x1[0]) +
                                                ② +lambda (x, y): x + f(y) +lambda x_y: x_y[0] + f(x_y[1]) +
                                                ③ +lambda (x, (y, z)): x + y + z +lambda x_y_z: x_y_z[0] + x_y_z[1][0] + x_y_z[1][1] +
                                                ④ +lambda x, y, z: x + y + z +unchanged

                                                1. If you had defined a lambda function that took a tuple of one item, in Python 3 that would become a lambda with references to x1[0]. The name x1 is autogenerated by the 2to3 script, based on the named arguments in the original tuple. @@ -823,39 +823,39 @@ except:

                                                  Special method attributes

                                                  In Python 2, class methods can reference the class object they are defined in, as well as the method object itself. im_self is the class instance object; the class im_func is the function object; im_class is the class of im_self (for bound methods) or the class that asked for the method (for unbound methods). In Python 3, these special method attributes have been renamed to follow the naming conventions of other attributes. - - - - - - - - - - - - - +
                                                  NotesPython 2Python 3
                                                  aClassInstance.aClassMethod.im_funcaClassInstance.aClassMethod.__func__
                                                  aClassInstance.aClassMethod.im_selfaClassInstance.aClassMethod.__self__
                                                  aClassInstance.aClassMethod.im_classaClassInstance.aClassMethod.self.__class__
                                                  Notes +Python 2 +Python 3 + +
                                                  +aClassInstance.aClassMethod.im_func +aClassInstance.aClassMethod.__func__ +
                                                  +aClassInstance.aClassMethod.im_self +aClassInstance.aClassMethod.__self__ +
                                                  +aClassInstance.aClassMethod.im_class +aClassInstance.aClassMethod.self.__class__

                                                  __nonzero__ special class attribute

                                                  In Python 2, you could build your own classes that could be used in a boolean context. For example, you could instantiate the class and then use the instance in an if statement. To do this, you defined a special __nonzero__() method which returned True or False, and it was called whenever the instance was used in a boolean context. In Python 3, you can still do this, but the name of the method has changed to __bool__(). - - - - - + + pass - + pass + - + pass +
                                                  NotesPython 2Python 3
                                                  Notes +Python 2 +Python 3 + +
                                                  class A:
                                                       def __nonzero__(self):
                                                  -        pass
                                                  class A:
                                                       def __bool__(self):
                                                  -        pass
                                                  class A:
                                                       def __nonzero__(self, x, y):
                                                  -        pass
                                                  no change
                                                  no change

                                                  1. Instead of __nonzero__(), Python 3 calls the __bool__() method when evaluating an instance in a boolean context. @@ -864,27 +864,27 @@ except:

                                                    Octal literals

                                                    The syntax for defining base 8 (octal) numbers has changed slightly between Python 2 and Python 3. - - - - - - - +
                                                    NotesPython 2Python 3
                                                    x = 0755x = 0o755
                                                    Notes +Python 2 +Python 3 + +
                                                    +x = 0755 +x = 0o755

                                                    sys.maxint

                                                    Due to the integration of the long and int types, the sys.maxint constant is no longer accurate. Because the value may still be useful in determining platform-specific capabilities, it has been retained but renamed as sys.maxsize. - - - - - - - - - - +
                                                    NotesPython 2Python 3
                                                    from sys import maxintfrom sys import maxsize
                                                    a_function(sys.maxint)a_function(sys.maxsize)
                                                    Notes +Python 2 +Python 3 + +
                                                    ① +from sys import maxint +from sys import maxsize +
                                                    ② +a_function(sys.maxint) +a_function(sys.maxsize)

                                                    1. maxint becomes maxsize. @@ -893,27 +893,27 @@ except:

                                                      callable() global function

                                                      In Python 2, you could check whether an object was callable (like a function) with the global callable() function. In Python 3, this global function has been eliminated. To check whether an object is callable, check for the existence of the __call__() special method. - - - - - - - +
                                                      NotesPython 2Python 3
                                                      callable(anything)hasattr(anything, "__call__")
                                                      Notes +Python 2 +Python 3 + +
                                                      +callable(anything) +hasattr(anything, "__call__")

                                                      zip() global function

                                                      In Python 2, the global zip() function took any number of sequences and returned a list of tuples. The first tuple contained the first item from each sequence; the second tuple contained the second item from each sequence; and so on. In Python 3, zip() returns an iterator instead of a list. - - - - - - - - - - +
                                                      NotesPython 2Python 3
                                                      zip(a, b, c)list(zip(a, b, c))
                                                      d.join(zip(a, b, c))no change
                                                      Notes +Python 2 +Python 3 + +
                                                      ① +zip(a, b, c) +list(zip(a, b, c)) +
                                                      ② +d.join(zip(a, b, c)) +no change

                                                      1. In the simplest form, you can get the old behavior of the zip() function by wrapping the return value in a call to list(), which will run through the iterator that zip() returns and return a real list of the results. @@ -922,53 +922,53 @@ except:

                                                        StandardError exception

                                                        In Python 2, StandardError was the base class for all built-in exceptions other than StopIteration, GeneratorExit, KeyboardInterrupt, and SystemExit. In Python 3, StandardError has been eliminated; use Exception instead. - - - - - - - - - - +
                                                        NotesPython 2Python 3
                                                        x = StandardError()x = Exception()
                                                        x = StandardError(a, b, c)x = Exception(a, b, c)
                                                        Notes +Python 2 +Python 3 + +
                                                        +x = StandardError() +x = Exception() +
                                                        +x = StandardError(a, b, c) +x = Exception(a, b, c)

                                                        types module constants

                                                        The types module contains a variety of constants to help you determine the type of an object. In Python 2, it contained constants for all primitive types like dict and int. In Python 3, these constants have been eliminated; just use the primitive type name instead. - - - - - - - - - - - - - - - - - - - - - - +
                                                        NotesPython 2Python 3
                                                        types.StringTypebytes
                                                        types.DictTypedict
                                                        types.IntTypeint
                                                        types.LongTypeint
                                                        types.ListTypelist
                                                        types.NoneTypetype(None)
                                                        Notes +Python 2 +Python 3 + +
                                                        +types.StringType +bytes +
                                                        +types.DictType +dict +
                                                        +types.IntType +int +
                                                        +types.LongType +int +
                                                        +types.ListType +list +
                                                        +types.NoneType +type(None)

                                                        isinstance() global function (3.1+)

                                                        The isinstance() function checks whether an object is an instance of a particular class or type. In Python 2, you could pass a tuple of types, and isinstance() would return True if the object was any of those types. In Python 3, you can still do this, but passing the same type twice is deprecated. - - - - - - - +
                                                        NotesPython 2Python 3
                                                        isinstance(x, (int, float, int))isinstance(x, (int, float))
                                                        Notes +Python 2 +Python 3 + +
                                                        +isinstance(x, (int, float, int)) +isinstance(x, (int, float))

                                                        The version of 2to3 that shipped with Python 3.0 would not fix these cases of isinstance() automatically. The fix first appeared in the 2to3 script that shipped with Python 3.1. @@ -976,33 +976,33 @@ except:

                                                        basestring datatype

                                                        Python 2 had two string types: Unicode and non-Unicode. But there was also another type, basestring. It was an abstract type, a superclass for both the str and unicode types. It couldn't be called or instantiated directly, but you could pass it to the global isinstance() function to check whether an object was either a Unicode or non-Unicode string. In Python 3, there is only one string type, so basestring has no reason to exist. - - - - - - - +
                                                        NotesPython 2Python 3
                                                        isinstance(x, basestring)isinstance(x, str)
                                                        Notes +Python 2 +Python 3 + +
                                                        +isinstance(x, basestring) +isinstance(x, str)

                                                        itertools module

                                                        Python 2.3 introduced the itertools module, which defined variants of the global zip(), map(), and filter() functions that returned iterators instead of lists. In Python 3, those global functions return iterators, so those functions in the itertools module have been eliminated. - - - - - - - - - - - - - - - - +
                                                        NotesPython 2Python 3
                                                        itertools.izip(a, b)zip(a, b)
                                                        itertools.imap(a, b)map(a, b)
                                                        itertools.ifilter(a, b)filter(a, b)
                                                        from itertools import imap, izip, foofrom itertools import foo
                                                        Notes +Python 2 +Python 3 + +
                                                        ① +itertools.izip(a, b) +zip(a, b) +
                                                        ② +itertools.imap(a, b) +map(a, b) +
                                                        ③ +itertools.ifilter(a, b) +filter(a, b) +
                                                        ④ +from itertools import imap, izip, foo +from itertools import foo

                                                        1. Instead of itertools.izip(), just use the global zip() function. @@ -1013,63 +1013,63 @@ except:

                                                          sys.exc_type, sys.exc_value, sys.exc_traceback

                                                          Python 2 had three variables in the sys module that you could access while an exception was being handled: sys.exc_type, sys.exc_value, sys.exc_traceback. (Actually, these date all the way back to Python 1.) Ever since Python 1.5, these variables have been deprecated in favor of sys.exc_info, which is a tuple that contains all three values. In Python 3, these individual variables have finally gone away; you must use sys.exc_info. - - - - - - - - - - - - - +
                                                          NotesPython 2Python 3
                                                          sys.exc_typesys.exc_info()[0]
                                                          sys.exc_valuesys.exc_info()[1]
                                                          sys.exc_tracebacksys.exc_info()[2]
                                                          Notes +Python 2 +Python 3 + +
                                                          +sys.exc_type +sys.exc_info()[0] +
                                                          +sys.exc_value +sys.exc_info()[1] +
                                                          +sys.exc_traceback +sys.exc_info()[2]

                                                          List comprehensions over tuples

                                                          In Python 2, if you wanted to code a list comprehension that iterated over a tuple, you did not need to put parentheses around the tuple values. In Python 3, explicit parentheses are required. - - - - - - - +
                                                          NotesPython 2Python 3
                                                          [i for i in 1, 2][i for i in (1, 2)]
                                                          Notes +Python 2 +Python 3 + +
                                                          +[i for i in 1, 2] +[i for i in (1, 2)]

                                                          os.getcwdu() function

                                                          Python 2 had a function named os.getcwd(), which returned the current working directory as a (non-Unicode) string. Because modern file systems can handle directory names in any character encoding, Python 2.3 introduced os.getcwdu(). The os.getcwdu() function returned the current working directory as a Unicode string. In Python 3, there is only one string type (Unicode), so os.getcwd() is all you need. - - - - - - - +
                                                          NotesPython 2Python 3
                                                          os.getcwdu()os.getcwd()
                                                          Notes +Python 2 +Python 3 + +
                                                          +os.getcwdu() +os.getcwd()

                                                          Metaclasses

                                                          In Python 2, you could create metaclasses either by defining the metaclass argument in the class declaration, or by defining a special class-level __metaclass__ attribute. In Python 3, the class-level attribute has been eliminated. - - - - - + - - + pass + + __metaclass__ = PapayaMeta - + pass + + __metaclass__ = PapayaMeta + pass
                                                          NotesPython 2Python 3
                                                          Notes +Python 2 +Python 3 + +
                                                          class C(metaclass=PapayaMeta):
                                                          -    pass
                                                          unchanged
                                                          unchanged +
                                                          class Whip:
                                                          -    __metaclass__ = PapayaMeta
                                                          class Whip(metaclass=PapayaMeta):
                                                          -    pass
                                                          class C(Whipper, Beater):
                                                          -    __metaclass__ = PapayaMeta
                                                          class C(Whipper, Beater, metaclass=PapayaMeta):
                                                          -    pass

                                                          1. Declaring the metaclass in the class declaration worked in Python 2, and it still works the same in Python 3. @@ -1084,19 +1084,19 @@ except:

                                                            The 2to3 script will not fix set() literals by default. To enable this fix, specify -f set_literal on the command line when you call 2to3.

                                                        - - - - - - - - - - - - - +
                                                        NotesBeforeAfter
                                                        set([1, 2, 3]){1, 2, 3}
                                                        set((1, 2, 3)){1, 2, 3}
                                                        set([i for i in a_sequence]){i for i in a_sequence}
                                                        Notes +Before +After + +
                                                        +set([1, 2, 3]) +{1, 2, 3} +
                                                        +set((1, 2, 3)) +{1, 2, 3} +
                                                        +set([i for i in a_sequence]) +{i for i in a_sequence}

                                                        buffer() global function (explicit)

                                                        Python objects implemented in C can export a “buffer interface,” which is a block of memory that is directly readable and writeable without copying. (That is exactly as powerful and scary as it sounds.) In Python 3, buffer() has been renamed to memoryview(). (It's a little more complicated than that, but you can almost certainly ignore the differences.) @@ -1104,13 +1104,13 @@ except:

                                                        The 2to3 script will not fix the buffer() function by default. To enable this fix, specify -f buffer on the command line when you call 2to3.

                                - - - - - - - +
                                NotesBeforeAfter
                                x = buffer(y)x = memoryview(y)
                                Notes +Before +After + +
                                +x = buffer(y) +x = memoryview(y)

                                Whitespace around commas (explicit)

                                Despite being draconian about whitespace for indenting and outdenting, Python is actually quite liberal about whitespace in other areas. Within lists, tuples, sets, and dictionaries, whitespace can appear before and after commas with no ill effects. However, the Python style guide states that commas should be preceded by zero spaces and followed by one. Although this is purely an aesthetic issue (the code works either way, in both Python 2 and Python 3), the 2to3 script can optionally fix this for you. @@ -1118,16 +1118,16 @@ except:

                                The 2to3 script will not fix whitespace around commas by default. To enable this fix, specify -f wscomma on the command line when you call 2to3.

                            - - - - - - - - - - +
                            NotesBeforeAfter
                            a ,ba, b
                            {a :b}{a: b}
                            Notes +Before +After + +
                            +a ,b +a, b +
                            +{a :b} +{a: b}

                            Common idioms (explicit)

                            There were a number of common idioms built up in the Python community. Some, like the while 1: loop, date back to Python 1. (Python didn't have a true boolean type until version 2.3, so developers used 1 and 0 instead.) Modern Python programmers should train their brains to use modern versions of these idioms instead. @@ -1135,27 +1135,27 @@ except:

                            The 2to3 script will not fix common idioms by default. To enable this fix, specify -f idioms on the command line when you call 2to3. - - - - - + + do_stuff() - - - - - - - + do_stuff() + +do_stuff(a_list) +do_stuff(a_list)
                            NotesBeforeAfter
                            Notes +Before +After + +
                            while 1:
                            -    do_stuff()
                            while True:
                            -    do_stuff()
                            type(x) == Tisinstance(x, T)
                            type(x) is Tisinstance(x, T)
                            +type(x) == T +isinstance(x, T) +
                            +type(x) is T +isinstance(x, T) +
                            a_list = list(a_sequence)
                             a_list.sort()
                            -do_stuff(a_list)
                            a_list = sorted(a_sequence)
                            -do_stuff(a_list)

                            FIXME: once the rest of the book is written, this appendix should contain copious links back to any chapter or section that touches on these features.

                            So Python is both dynamically typed (because it doesn't use explicit datatype declarations) and strongly typed (because once a variable has a datatype, it actually matters).

                            If you have experience in other programming languages, this table may help you visualize how Python compares to them: - - - +
                            Statically typedDynamically typed
                            Weakly typedC, Objective-CJavaScript, Perl 5, PHP
                            Strongly typedPascal, JavaPython, Ruby
                            Statically typedDynamically typed +
                            Weakly typedC, Objective-CJavaScript, Perl 5, PHP +
                            Strongly typedPascal, JavaPython, Ruby

                            Writing Readable Code

                            I won't bore you with a long finger-wagging speech about the importance of documenting your code. Just know that code is written once but read many times, and the most important audience for your code is yourself, six months after writing it (i.e. after you've forgotten everything but need to fix something). Python makes it easy to write readable code, so take advantage of it. You'll thank me in six months.