diff --git a/index.html b/index.html index d5d5190..fe29e5e 100644 --- a/index.html +++ b/index.html @@ -282,9 +282,10 @@ h3{margin-left:3.5em}
exec statement
execfile statement (3.1+)
repr literals (backticks)
+try...except statement
raise statement
-throw statement
+throw method on generators
xrange() global function
raw_input() and input() global functions
func_* function attributes
@@ -305,10 +306,13 @@ h3{margin-left:3.5em}
os.getcwdu() function
set() literals (explicit)
-buffer() global function (explicit)
-This site is optimized for Lynx just because fuck you.
I’m told it also looks good in graphical browsers.
diff --git a/porting-code-to-python-3-with-2to3.html b/porting-code-to-python-3-with-2to3.html
index ad3f6ad..4f42a34 100644
--- a/porting-code-to-python-3-with-2to3.html
+++ b/porting-code-to-python-3-with-2to3.html
@@ -34,6 +34,7 @@ h3:before{counter-increment:h3;content:"A." counter(h2) "." counter(h3) ". "}
next() iterator method
filter() global function
map() global function
reduce() global function (3.1+)
@@ -42,16 +43,16 @@ h3:before{counter-increment:h3;content:"A." counter(h2) "." counter(h3) ". "}
exec statement
execfile statement (3.1+)
repr literals (backticks)
+try...except statement
raise statement
-throw statement
+throw method on generators
xrange() global function
raw_input() and input() global functions
func_* function attributes
xreadlines() I/O method
lambda functions with multiple parameters
next() iterator method
__nonzero__ special class attribute
sys.maxint
@@ -66,10 +67,13 @@ h3:before{counter-increment:h3;content:"A." counter(h2) "." counter(h3) ". "}
os.getcwdu() function
set() literals (explicit)
-buffer() global function (explicit)
-Python 3 comes with a utility script called 2to3, which takes your actual Python 2 source code as input and auto-converts as much as it can to Python 3. Case study: porting chardet to Python 3 describes how to run the 2to3 script, then shows some things it can't fix automatically. This appendix documents what it can fix automatically.
@@ -252,7 +256,7 @@ h3:before{counter-increment:h3;content:"A." counter(h2) "." counter(h3) ". "}
Several modules in the Python Standard Library have been renamed. Several other modules which are related to each other have been combined or reorganized to make their association more logical. -
http packagehttpIn Python 3, several related HTTP modules have been combined into a single package, http.
import dbm |
-
xmlrpc packagexmlrpcXML-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.
| Notes | +Python 2 | +Python 3 | +
|---|---|---|
| ① | +anIterator.next() |
+next(anIterator) |
| ② | +a_function_that_returns_an_iterator().next() |
+next(a_function_that_returns_an_iterator()) |
| ③ | + |
+ |
| ④ | + |
+no change |
| ⑤ | + |
+ |
next() method, you now pass the iterator itself to the global next() function.
+next() function. (The 2to3 script is smart enough to convert this properly.)
+__next__() special method.
+next() that takes one or more arguments, 2to3 will not touch it. This class can not be used as an iterator, because its next() method takes arguments.
+next() function. In this case, you need to call the iterator's special __next()__ method to get the next item in the sequence. (Alternatively, you could also refactor the code so the local variable wasn't named next, but 2to3 will not do that for you automatically.)
+filter() global functionIn 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 interator, not a list.
skip over this table @@ -624,7 +669,7 @@ reduce(a, b, c)
2to3 tool is smart enough to convert this into nested calls to repr().
try...except statementThe syntax for catching exceptions has changed slightly between Python 2 and 3. +
The syntax for catching exceptions has changed slightly between Python 2 and Python 3.
| Notes | @@ -665,7 +710,7 @@ except:
|---|
| Notes | @@ -708,19 +753,19 @@ except:Python 3 | ||
|---|---|---|---|
| ① | -aGenerator.throw(MyException) |
+a_generator.throw(MyException) |
no change |
| ② | -aGenerator.throw(MyException, "error message") |
-aGenerator.throw(MyException("error message")) | a_generator.throw(MyException, "error message") |
+a_generator.throw(MyException("error message")) |
| ③ | -aGenerator.throw("error message") |
+a_generator.throw("error message") |
unsupported |
2to3 script will display a warning telling you that you will need to fix this code manually.
xrange() global functionIn 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.
@@ -777,7 +822,7 @@ except:
input() function and pass the result to eval().
func_* function attributesFIXME intro +
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.
| Notes | @@ -785,38 +830,38 @@ except:Python 3 | |
|---|---|---|
| ① | -a_function.func_closure |
-a_function.__closure__ | a_function.func_name |
+a_function.__name__ |
| ② | a_function.func_doc |
a_function.__doc__ |
| ③ | -a_function.func_name |
-a_function.__name__ |
| ④ | a_function.func_defaults |
a_function.__defaults__ |
| ④ | +a_function.func_dict |
+a_function.__dict__ |
| ⑤ | -a_function.func_code |
-a_function.__code__ | a_function.func_closure |
+a_function.__closure__ |
| ⑥ | a_function.func_globals |
a_function.__globals__ |
| ⑦ | -a_function.func_dict |
-a_function.__dict__ | a_function.func_code |
+a_function.__code__ |
__name__ attribute (previously func_name) contains the function's name.
+__doc__ attribute (previously func_doc) contains the docstring that you defined in the function's source code.
+__defaults__ attribute (previously func_defaults) is a tuple containing default argument values for those arguments that have default values.
+__dict__ attribute (previously func_dict) is the namespace supporting arbitrary function attributes.
+__closure__ attribute (previously func_closure) is a tuple of cells that contain bindings for the function's free variables.
+__globals__ attribute (previously func_globals) is a reference to the global namespace of the module in which the function was defined.
+__code__ attribute (previously func_code) is a code object representing the compiled function body.
xreadlines() I/O methodIn 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 [FIXME exact version?] added the capability to file objects themselves.
+
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.
| Notes | @@ -835,7 +880,7 @@ except:
|---|
| Notes | @@ -844,7 +889,7 @@ except:||
|---|---|---|
| ① | lambda (x,): x + f(x) |
-lambda x1: x1[0] + f(x1[1]) | 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[0] + x_y_z[1][0] + x_y_z[1][1] |
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.
+lambda function with a two-item tuple (x, y) gets converted to x_y with positional arguments x_y[0] and x_y[1].
+2to3 script can even handle lambda functions with nested tuples of named arguments. The resulting Python 3 code is a bit unreadable, but it works the same as the old code did in Python 2.
FIXME intro +
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.
| Notes | @@ -875,54 +920,9 @@ except:aClassInstance.aClassMethod.im_class |
aClassInstance.aClassMethod.self.__class__ |
|---|
next() iterator methodIn 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.
-
| Notes | -Python 2 | -Python 3 | -
|---|---|---|
| ① | -anIterator.next() |
-next(anIterator) |
| ② | -a_function_that_returns_an_iterator().next() |
-next(a_function_that_returns_an_iterator()) |
| ③ | - |
- |
| ④ | - |
-no change |
| ⑤ | - |
- |
next() method, you now pass the iterator itself to the global next() function.
-next() function. (The 2to3 script is smart enough to convert this properly.)
-__next__() special method.
-next() that takes one or more arguments, 2to3 will not touch it. This class can not be used as an iterator, because its next() method takes arguments.
-next() function. In this case, you need to call the iterator's special __next()__ method to get the next item in the sequence. (Alternatively, you could also refactor the code so the local variable wasn't named next, but 2to3 will not do that for you automatically.)
-
__nonzero__ special class attributeFIXME intro +
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__().
| Notes | @@ -943,8 +943,8 @@ for an_iterator in a_sequence_of_iterators:no change |
|---|
__nonzero__(), Python 3 calls the __bool__() method when evaluating an instance in a boolean context.
+__nonzero__() method that takes arguments, the 2to3 tool will assume that you were using it for some other purpose, and it will not make any changes.
The syntax for defining base 8 (octal) numbers has changed slightly between Python 2 and Python 3. @@ -992,7 +992,7 @@ for an_iterator in a_sequence_of_iterators:
zip() global functionFIXME intro +
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.
| Notes | @@ -1007,28 +1007,25 @@ for an_iterator in a_sequence_of_iterators:no change |
|---|
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.
+join() method), the iterator that zip() returns will work just fine. The 2to3 script is smart enough to detect these cases and make no change to your code.
StandardError() exceptionFIXME intro +
StandardError exceptionIn 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.
| Notes | Python 2 | Python 3 |
|---|---|---|
| ① | +||
x = StandardError() |
x = Exception() | |
| ② | +||
x = StandardError(a, b, c) |
x = Exception(a, b, c) |
types module constantsThe 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.
skip over this table @@ -1087,7 +1084,7 @@ for an_iterator in a_sequence_of_iterators:
itertools moduleFIXME intro +
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.
| Notes | Python 2 | @@ -1103,18 +1100,14 @@ for an_iterator in a_sequence_of_iterators:itertools.ifilter(a, b) |
filter(a, b) |
|---|---|---|---|
| ④ | -itertools.ifilterfalse(a, b) |
-filterfalse(a, b) | |
| ⑤ | from itertools import imap, izip, foo |
from itertools import foo |
itertools.izip(), just use the global zip() function.
+itertools.imap(), just use map().
+itertools.ifilter() becomes filter().
+itertools module still exists in Python 3, it just doesn't have the functions that have migrated to the global namespace. The 2to3 script is smart enough to remove the specific imports that no longer exist, while leaving other imports intact.
sys.exc_type, sys.exc_value, sys.exc_tracebackPython 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.
@@ -1124,19 +1117,19 @@ for an_iterator in a_sequence_of_iterators:
sys.exc_typesys.exc_info()[0]sys.exc_valuesys.exc_info()[1]sys.exc_tracebacksys.exc_info()[2]
FIXME intro +
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.
| Notes | @@ -1149,7 +1142,7 @@ for an_iterator in a_sequence_of_iterators:
|---|
os.getcwdu() functionPython 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, so os.getcwd() is all you need.
+
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.
| Notes | @@ -1162,7 +1155,7 @@ for an_iterator in a_sequence_of_iterators:
|---|
FIXME intro +
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.
| Notes | @@ -1170,22 +1163,29 @@ for an_iterator in a_sequence_of_iterators:Python 3 | ||||
|---|---|---|---|---|---|
| ① | + |
+unchanged | |||
| ② | |
| |||
| ② | - |
2to3 script is smart enough to construct a valid class declaration, even if the class is inherited from one or more base classes.
set() literals (explicit)FIXME intro +
The rest of the “fixes” listed here aren't really fixes per se. That is, the things they change are matters of style, not substance. They work just as well in Python 3 as they do in Python 2, but the developers of Python have a vested interest in making Python code as uniform as possible. To that end, there is an official Python style guide which outlines — in excruciating detail — all sorts of nitpicky details that you almost certainly don't care about. And given that 2to3 provides such a great infrastructure for converting Python code from one thing to another, the authors took it upon themselves to add a few optional features to improve the readability of your Python programs.
+
set() literals (explicit)In Python 2, the only way to define a literal set in your code was to call set(a_sequence). This still works in Python 3, but a clearer way of doing it is to use the new set literal notation: curly braces. (Dictionaries are also defined with curly braces, which makes sense once you think about it, because dictionaries are just sets of key-value pairs.)
☞
The
2to3script will not fixset()literals by default. To enable this fix, specify -f set_literal on the command line when you call2to3. @@ -1193,26 +1193,22 @@ for an_iterator in a_sequence_of_iterators:-
- Notes -Python 2 -Python 3 +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)FIXME intro +
+
+
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 tomemoryview(). (It's a little more complicated than that, but you can almost certainly ignore the differences.)☞
The
2to3script will not fix thebuffer()function by default. To enable this fix, specify -f buffer on the command line when you call2to3. @@ -1220,18 +1216,16 @@ for an_iterator in a_sequence_of_iterators:-
- Notes -Python 2 -Python 3 +Before +After ① +x = buffer(y)x = memoryview(y)-
-- ... -
Whitespace around commas (explicit)
-FIXME intro +
+
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
2to3script can optionally fix this for you.☞
The
2to3script will not fix whitespace around commas by default. To enable this fix, specify -f wscomma on the command line when you call2to3. @@ -1239,22 +1233,19 @@ for an_iterator in a_sequence_of_iterators:-
- Notes -Python 2 -Python 3 +Before +After ① +- a ,ba, b② +{a :b}{a: b}-
-- ... -
- ... -
Common idioms (explicit)
-FIXME intro +
+
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 used1and0instead.) Modern Python programmers should train their brains to use modern versions of these idioms instead.☞
The
2to3script will not fix common idioms by default. To enable this fix, specify -f idioms on the command line when you call2to3. @@ -1262,33 +1253,28 @@ for an_iterator in a_sequence_of_iterators:-
- Notes -Python 2 -Python 3 +Before +After ① +- while 1: do_stuff()while True: do_stuff()② +- type(x) == Tisinstance(x, T)③ +- type(x) is Tisinstance(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.
© 2001-4, 2009 ℳark Pilgrim, CC-BY-3.0