diff python 2 and 3

This commit is contained in:
rasbt 2014-04-17 22:44:15 -04:00
parent 997a60f6b0
commit 215228201d
2 changed files with 777 additions and 10 deletions

View File

@ -1,7 +1,7 @@
{
"metadata": {
"name": "",
"signature": "sha256:2e4322ee7bffc6746194af4b3ac6bb9cd8794c14bea2575e3097821a7d5f9b52"
"signature": "sha256:ef925e4eaf58c6daf50a495a77d38aa0b02a365dfc972bb5c0174332360b5adb"
},
"nbformat": 3,
"nbformat_minor": 0,
@ -59,7 +59,7 @@
"- [Don't use mutable objects as default arguments for functions!](#def_mutable_func)\n",
"- [Be aware of the consuming generator](#consuming_generator)\n",
"- [`bool` is a subclass of `int`](#bool_int)\n",
"- [About lambda and closures-in-a-loop pitfall](#lambda_closure)\n",
"- [About lambda-in-closures and-a-loop pitfall](#lambda_closure)\n",
"- [Python's LEGB scope resolution and the keywords `global` and `nonlocal`](#python_legb)\n",
"- [When mutable contents of immutable tuples aren't so mutable](#immutable_tuple)\n",
"- [List comprehensions are fast, but generators are faster!?](#list_generator)\n",
@ -67,7 +67,9 @@
"- [The consequences of modifying a list when looping through it](#looping_pitfall)\n",
"- [Dynamic binding and typos in variable names](#dynamic_binding)\n",
"- [List slicing using indexes that are \"out of range](#out_of_range_slicing)\n",
"- [Reusing global variable names and UnboundLocalErrors](#unboundlocalerror)"
"- [Reusing global variable names and UnboundLocalErrors](#unboundlocalerror)\n",
"- [Creating copies of mutable objects](#copy_mutable)\n",
"- [Key differences between Python 2 and 3](#python_differences)"
]
},
{
@ -710,7 +712,7 @@
"<br>\n",
"<a name='lambda_closure'></a>\n",
"\n",
"## About lambda and closures-in-a-loop pitfall\n",
"## About lambda-in-closures-and-a-loop pitfall\n",
"\n",
"Remember the [\"consuming generators\"](consuming_generators)? This example is somewhat related, but the result might still come unexpected. \n",
"\n",
@ -1697,10 +1699,370 @@
],
"prompt_number": 43
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"<br>\n",
"<a name='copy_mutable'></a>\n",
"## Creating copies of mutable objects\n",
"\n",
"Let's assume a scenario where we want to duplicate sub`list`s of values stored in another list. If we want to create independent sub`list` object, using the arithmetic multiplication operator could lead to rather unexpected (or undesired) results:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"input": [
"my_list1 = [[1, 2, 3]] * 2\n",
"\n",
"print('initially ---> ', my_list1)\n",
"\n",
"# modify the 1st element of the 2nd sublist\n",
"my_list1[1][0] = 'a'\n",
"print(\"after my_list1[1][0] = 'a' ---> \", my_list1)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"initially ---> [[1, 2, 3], [1, 2, 3]]\n",
"after my_list1[1][0] = 'a' ---> [['a', 2, 3], ['a', 2, 3]]\n"
]
}
],
"prompt_number": 24
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"<br>\n",
"In this case, we should better create \"new\" objects:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"my_list2 = [[1, 2, 3] for i in range(2)]\n",
"\n",
"print('initially: ---> ', my_list2)\n",
"\n",
"# modify the 1st element of the 2nd sublist\n",
"my_list2[1][0] = 'a'\n",
"print(\"after my_list2[1][0] = 'a': ---> \", my_list2)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"initially: ---> [[1, 2, 3], [1, 2, 3]]\n",
"after my_list2[1][0] = 'a': ---> [[1, 2, 3], ['a', 2, 3]]\n"
]
}
],
"prompt_number": 25
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"And here is the proof:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for a,b in zip(my_list1, my_list2):\n",
" print('id my_list1: {}, id my_list2: {}'.format(id(a), id(b)))"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"id my_list1: 4350764680, id my_list2: 4350766472\n",
"id my_list1: 4350764680, id my_list2: 4350766664\n"
]
}
],
"prompt_number": 26
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"<br>\n",
"## Key differences between Python 2 and 3\n",
"\n",
"There are some good articles already that are summarizing the differences between Python 2 and 3, e.g., \n",
"- [https://wiki.python.org/moin/Python2orPython3](https://wiki.python.org/moin/Python2orPython3)\n",
"- [https://docs.python.org/3.0/whatsnew/3.0.html](https://docs.python.org/3.0/whatsnew/3.0.html)\n",
"- [http://python3porting.com/differences.html](http://python3porting.com/differences.html)\n",
"- [https://docs.python.org/3/howto/pyporting.html](https://docs.python.org/3/howto/pyporting.html) \n",
"etc.\n",
"\n",
"But it might be still worthwhile, especially for Python newcomers, to take a look at some of those!\n",
"(Note: the the code was executed in Python 3.4.0 and Python 2.7.5 and copied from interactive shell sessions.)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"### Unicode...\n",
"####- Python 2: \n",
"We have ASCII `str()` types, separate `unicode()`, but no `byte` type\n",
"####- Python 3: \n",
"Now, we finally have Unicode (utf-8) `str`ings, and 2 byte classes: `byte` and `bytearray`s"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#############\n",
"# Python 2\n",
"#############\n",
"\n",
">>> type(unicode('is like a python3 str()'))\n",
"<type 'unicode'>\n",
"\n",
">>> type(b'byte type does not exist')\n",
"<type 'str'>\n",
"\n",
">>> 'they are really' + b' the same'\n",
"'they are really the same'\n",
"\n",
">>> type(bytearray(b'bytearray oddly does exist though'))\n",
"<type 'bytearray'>\n",
"\n",
"#############\n",
"# Python 3\n",
"#############\n",
"\n",
">>> print('strings are now utf-8 \\u03BCnico\\u0394\u00e9!')\n",
"strings are now utf-8 \u03bcnico\u0394\u00e9!\n",
"\n",
"\n",
">>> type(b' and we have byte types for storing data')\n",
"<class 'bytes'>\n",
"\n",
">>> type(bytearray(b'but also bytearrays for those who prefer them over strings'))\n",
"<class 'bytearray'>\n",
"\n",
">>> 'string' + b'bytes for data'\n",
"Traceback (most recent call last):s\n",
" File \"<stdin>\", line 1, in <module>\n",
"TypeError: Can't convert 'bytes' object to str implicitly"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### The print statement\n",
"Very trivial, but this change makes sense, Python 3 now only accepts `print`s with proper parentheses - just like the other function calls ..."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
">>> print 'Hello, World!'\n",
"Hello, World!\n",
">>> print('Hello, World!')\n",
"Hello, World!\n",
"\n",
"# Python 3\n",
">>> print('Hello, World!')\n",
"Hello, World!\n",
">>> print 'Hello, World!'\n",
" File \"<stdin>\", line 1\n",
" print 'Hello, World!'\n",
" ^\n",
"SyntaxError: invalid syntax"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And if we want to print the output of 2 consecutive print functions on the same line, you would use a comma in Python 2, and a `end=\"\"` in Python 3:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
">>> print \"line 1\", ; print 'same line'\n",
"line 1 same line\n",
"\n",
"# Python 3\n",
">>> print(\"line 1\", end=\"\") ; print (\" same line\")\n",
"line 1 same line"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Integer division\n",
"This is a pretty dangerous thing if you are porting code, or executing Python 3 code in Python 2 since the change in integer-division behavior can often go unnoticed. \n",
"So, I still tend to use a `float(3/2)` or `3/2.0` instead of a `3/2` in my Python 3 scripts to save the Python 2 guys some trouble ... (PS: and vice versa, you can `from __future__ import division` in your Python 2 scripts)."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
">>> 3 / 2\n",
"1\n",
">>> 3 // 2\n",
"1\n",
">>> 3 / 2.0\n",
"1.5\n",
">>> 3 // 2.0\n",
"1.0\n",
"\n",
"# Python 3\n",
">>> 3 / 2\n",
"1.5\n",
">>> 3 // 2\n",
"1\n",
">>> 3 / 2.0\n",
"1.5\n",
">>> 3 // 2.0\n",
"1.0"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### `xrange()` \n",
"`xrange()` was pretty popular in Python 2.x if you wanted to create an iterable object. The behavior was quite similar to a generator ('lazy evaluation'), but you could iterate over it infinitely. The advantage was that it was generally faster than `range()` (e.g., in a for-loop) - not if you had to iterate over the list multiple times, since the generation happens every time from scratch! \n",
"In Python 3, the `range()` was implemented like the `xrange()` function so that a dedicated `xrange()` function does not exist anymore."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
"> python -m timeit 'for i in range(1000000):' ' pass'\n",
"10 loops, best of 3: 66 msec per loop\n",
"\n",
" > python -m timeit 'for i in xrange(1000000):' ' pass'\n",
"10 loops, best of 3: 27.8 msec per loop\n",
"\n",
"# Python 3\n",
"> python3 -m timeit 'for i in range(1000000):' ' pass'\n",
"10 loops, best of 3: 51.1 msec per loop\n",
"\n",
"> python3 -m timeit 'for i in xrange(1000000):' ' pass'\n",
"Traceback (most recent call last):\n",
" File \"/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/timeit.py\", line 292, in main\n",
" x = t.timeit(number)\n",
" File \"/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/timeit.py\", line 178, in timeit\n",
" timing = self.inner(it, self.timer)\n",
" File \"<timeit-src>\", line 6, in inner\n",
" for i in xrange(1000000):\n",
"NameError: name 'xrange' is not defined"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Raising exceptions\n",
"\n",
"Where Python 2 accepts both notations, the 'old' and the 'new' way, Python 3 chokes (and raises a `SyntaxError` in turn) if we don't enclose the exception argument in parentheses:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
">>> raise IOError, \"file error\"\n",
"Traceback (most recent call last):\n",
" File \"<stdin>\", line 1, in <module>\n",
"IOError: file error\n",
">>> raise IOError(\"file error\")\n",
"Traceback (most recent call last):\n",
" File \"<stdin>\", line 1, in <module>\n",
"IOError: file error\n",
"\n",
" \n",
"# Python 3 \n",
">>> raise IOError, \"file error\"\n",
" File \"<stdin>\", line 1\n",
" raise IOError, \"file error\"\n",
" ^\n",
"SyntaxError: invalid syntax\n",
">>> raise IOError(\"file error\")\n",
"Traceback (most recent call last):\n",
" File \"<stdin>\", line 1, in <module>\n",
"OSError: file error"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
">>> try:\n",
"... blabla\n",
"... except NameError, err:\n",
"... print err, '--> our error msg'\n",
"... \n",
"name 'blabla' is not defined --> our error msg\n",
"\n",
"# Python 3\n",
">>> try:\n",
"... blabla\n",
"... except NameError as err:\n",
"... print(err, '--> our error msg')\n",
"... \n",
"name 'blabla' is not defined --> our error msg\n"
],
"language": "python",
"metadata": {},
"outputs": []

View File

@ -1,7 +1,7 @@
{
"metadata": {
"name": "",
"signature": "sha256:2e4322ee7bffc6746194af4b3ac6bb9cd8794c14bea2575e3097821a7d5f9b52"
"signature": "sha256:ce4b364bfb6414a1b40e25c6ed5320cec6bdbb11d75ce3e44632fe27504ace7e"
},
"nbformat": 3,
"nbformat_minor": 0,
@ -59,7 +59,7 @@
"- [Don't use mutable objects as default arguments for functions!](#def_mutable_func)\n",
"- [Be aware of the consuming generator](#consuming_generator)\n",
"- [`bool` is a subclass of `int`](#bool_int)\n",
"- [About lambda and closures-in-a-loop pitfall](#lambda_closure)\n",
"- [About lambda-in-closures and-a-loop pitfall](#lambda_closure)\n",
"- [Python's LEGB scope resolution and the keywords `global` and `nonlocal`](#python_legb)\n",
"- [When mutable contents of immutable tuples aren't so mutable](#immutable_tuple)\n",
"- [List comprehensions are fast, but generators are faster!?](#list_generator)\n",
@ -67,7 +67,9 @@
"- [The consequences of modifying a list when looping through it](#looping_pitfall)\n",
"- [Dynamic binding and typos in variable names](#dynamic_binding)\n",
"- [List slicing using indexes that are \"out of range](#out_of_range_slicing)\n",
"- [Reusing global variable names and UnboundLocalErrors](#unboundlocalerror)"
"- [Reusing global variable names and UnboundLocalErrors](#unboundlocalerror)\n",
"- [Creating copies of mutable objects](#copy_mutable)\n",
"- [Key differences between Python 2 and 3](#python_differences)"
]
},
{
@ -710,7 +712,7 @@
"<br>\n",
"<a name='lambda_closure'></a>\n",
"\n",
"## About lambda and closures-in-a-loop pitfall\n",
"## About lambda-in-closures-and-a-loop pitfall\n",
"\n",
"Remember the [\"consuming generators\"](consuming_generators)? This example is somewhat related, but the result might still come unexpected. \n",
"\n",
@ -1697,10 +1699,413 @@
],
"prompt_number": 43
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"<br>\n",
"<a name='copy_mutable'></a>\n",
"## Creating copies of mutable objects\n",
"\n",
"Let's assume a scenario where we want to duplicate sub`list`s of values stored in another list. If we want to create independent sub`list` object, using the arithmetic multiplication operator could lead to rather unexpected (or undesired) results:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"input": [
"my_list1 = [[1, 2, 3]] * 2\n",
"\n",
"print('initially ---> ', my_list1)\n",
"\n",
"# modify the 1st element of the 2nd sublist\n",
"my_list1[1][0] = 'a'\n",
"print(\"after my_list1[1][0] = 'a' ---> \", my_list1)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"initially ---> [[1, 2, 3], [1, 2, 3]]\n",
"after my_list1[1][0] = 'a' ---> [['a', 2, 3], ['a', 2, 3]]\n"
]
}
],
"prompt_number": 24
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"<br>\n",
"In this case, we should better create \"new\" objects:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"my_list2 = [[1, 2, 3] for i in range(2)]\n",
"\n",
"print('initially: ---> ', my_list2)\n",
"\n",
"# modify the 1st element of the 2nd sublist\n",
"my_list2[1][0] = 'a'\n",
"print(\"after my_list2[1][0] = 'a': ---> \", my_list2)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"initially: ---> [[1, 2, 3], [1, 2, 3]]\n",
"after my_list2[1][0] = 'a': ---> [[1, 2, 3], ['a', 2, 3]]\n"
]
}
],
"prompt_number": 25
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"And here is the proof:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for a,b in zip(my_list1, my_list2):\n",
" print('id my_list1: {}, id my_list2: {}'.format(id(a), id(b)))"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"id my_list1: 4350764680, id my_list2: 4350766472\n",
"id my_list1: 4350764680, id my_list2: 4350766664\n"
]
}
],
"prompt_number": 26
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"<br>\n",
"<a name='python_differences'></a>\n",
"## Key differences between Python 2 and 3\n",
"\n",
"There are some good articles already that are summarizing the differences between Python 2 and 3, e.g., \n",
"- [https://wiki.python.org/moin/Python2orPython3](https://wiki.python.org/moin/Python2orPython3)\n",
"- [https://docs.python.org/3.0/whatsnew/3.0.html](https://docs.python.org/3.0/whatsnew/3.0.html)\n",
"- [http://python3porting.com/differences.html](http://python3porting.com/differences.html)\n",
"- [https://docs.python.org/3/howto/pyporting.html](https://docs.python.org/3/howto/pyporting.html) \n",
"etc.\n",
"\n",
"But it might be still worthwhile, especially for Python newcomers, to take a look at some of those!\n",
"(Note: the the code was executed in Python 3.4.0 and Python 2.7.5 and copied from interactive shell sessions.)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"### Unicode...\n",
"####- Python 2: \n",
"We have ASCII `str()` types, separate `unicode()`, but no `byte` type\n",
"####- Python 3: \n",
"Now, we finally have Unicode (utf-8) `str`ings, and 2 byte classes: `byte` and `bytearray`s"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#############\n",
"# Python 2\n",
"#############\n",
"\n",
">>> type(unicode('is like a python3 str()'))\n",
"<type 'unicode'>\n",
"\n",
">>> type(b'byte type does not exist')\n",
"<type 'str'>\n",
"\n",
">>> 'they are really' + b' the same'\n",
"'they are really the same'\n",
"\n",
">>> type(bytearray(b'bytearray oddly does exist though'))\n",
"<type 'bytearray'>\n",
"\n",
"#############\n",
"# Python 3\n",
"#############\n",
"\n",
">>> print('strings are now utf-8 \\u03BCnico\\u0394\u00e9!')\n",
"strings are now utf-8 \u03bcnico\u0394\u00e9!\n",
"\n",
"\n",
">>> type(b' and we have byte types for storing data')\n",
"<class 'bytes'>\n",
"\n",
">>> type(bytearray(b'but also bytearrays for those who prefer them over strings'))\n",
"<class 'bytearray'>\n",
"\n",
">>> 'string' + b'bytes for data'\n",
"Traceback (most recent call last):s\n",
" File \"<stdin>\", line 1, in <module>\n",
"TypeError: Can't convert 'bytes' object to str implicitly"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### The print statement\n",
"Very trivial, but this change makes sense, Python 3 now only accepts `print`s with proper parentheses - just like the other function calls ..."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
">>> print 'Hello, World!'\n",
"Hello, World!\n",
">>> print('Hello, World!')\n",
"Hello, World!\n",
"\n",
"# Python 3\n",
">>> print('Hello, World!')\n",
"Hello, World!\n",
">>> print 'Hello, World!'\n",
" File \"<stdin>\", line 1\n",
" print 'Hello, World!'\n",
" ^\n",
"SyntaxError: invalid syntax"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And if we want to print the output of 2 consecutive print functions on the same line, you would use a comma in Python 2, and a `end=\"\"` in Python 3:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
">>> print \"line 1\", ; print 'same line'\n",
"line 1 same line\n",
"\n",
"# Python 3\n",
">>> print(\"line 1\", end=\"\") ; print (\" same line\")\n",
"line 1 same line"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Integer division\n",
"This is a pretty dangerous thing if you are porting code, or executing Python 3 code in Python 2 since the change in integer-division behavior can often go unnoticed. \n",
"So, I still tend to use a `float(3/2)` or `3/2.0` instead of a `3/2` in my Python 3 scripts to save the Python 2 guys some trouble ... (PS: and vice versa, you can `from __future__ import division` in your Python 2 scripts)."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
">>> 3 / 2\n",
"1\n",
">>> 3 // 2\n",
"1\n",
">>> 3 / 2.0\n",
"1.5\n",
">>> 3 // 2.0\n",
"1.0\n",
"\n",
"# Python 3\n",
">>> 3 / 2\n",
"1.5\n",
">>> 3 // 2\n",
"1\n",
">>> 3 / 2.0\n",
"1.5\n",
">>> 3 // 2.0\n",
"1.0"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### `xrange()` \n",
"`xrange()` was pretty popular in Python 2.x if you wanted to create an iterable object. The behavior was quite similar to a generator ('lazy evaluation'), but you could iterate over it infinitely. The advantage was that it was generally faster than `range()` (e.g., in a for-loop) - not if you had to iterate over the list multiple times, since the generation happens every time from scratch! \n",
"In Python 3, the `range()` was implemented like the `xrange()` function so that a dedicated `xrange()` function does not exist anymore."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
"> python -m timeit 'for i in range(1000000):' ' pass'\n",
"10 loops, best of 3: 66 msec per loop\n",
"\n",
" > python -m timeit 'for i in xrange(1000000):' ' pass'\n",
"10 loops, best of 3: 27.8 msec per loop\n",
"\n",
"# Python 3\n",
"> python3 -m timeit 'for i in range(1000000):' ' pass'\n",
"10 loops, best of 3: 51.1 msec per loop\n",
"\n",
"> python3 -m timeit 'for i in xrange(1000000):' ' pass'\n",
"Traceback (most recent call last):\n",
" File \"/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/timeit.py\", line 292, in main\n",
" x = t.timeit(number)\n",
" File \"/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/timeit.py\", line 178, in timeit\n",
" timing = self.inner(it, self.timer)\n",
" File \"<timeit-src>\", line 6, in inner\n",
" for i in xrange(1000000):\n",
"NameError: name 'xrange' is not defined"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Raising exceptions\n",
"\n",
"Where Python 2 accepts both notations, the 'old' and the 'new' way, Python 3 chokes (and raises a `SyntaxError` in turn) if we don't enclose the exception argument in parentheses:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
">>> raise IOError, \"file error\"\n",
"Traceback (most recent call last):\n",
" File \"<stdin>\", line 1, in <module>\n",
"IOError: file error\n",
">>> raise IOError(\"file error\")\n",
"Traceback (most recent call last):\n",
" File \"<stdin>\", line 1, in <module>\n",
"IOError: file error\n",
"\n",
" \n",
"# Python 3 \n",
">>> raise IOError, \"file error\"\n",
" File \"<stdin>\", line 1\n",
" raise IOError, \"file error\"\n",
" ^\n",
"SyntaxError: invalid syntax\n",
">>> raise IOError(\"file error\")\n",
"Traceback (most recent call last):\n",
" File \"<stdin>\", line 1, in <module>\n",
"OSError: file error"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Handling exceptions\n",
"\n",
"Also the handling of excecptions has slightly changed in Python 3. Now, we have to use the `as` keyword!"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
">>> try:\n",
"... blabla\n",
"... except NameError, err:\n",
"... print err, '--> our error msg'\n",
"... \n",
"name 'blabla' is not defined --> our error msg\n",
"\n",
"# Python 3\n",
">>> try:\n",
"... blabla\n",
"... except NameError as err:\n",
"... print(err, '--> our error msg')\n",
"... \n",
"name 'blabla' is not defined --> our error msg"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### The `next()` function and `.next()` method\n",
"\n",
"Where you can use both function and method in Python 2.7.5, the `next()` function is all that remain in Python 3!"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
">>> my_generator = (letter for letter in 'abcdefg')\n",
">>> my_generator.next()\n",
"'a'\n",
">>> next(my_generator)\n",
"'b'\n",
"\n",
"# Python 3\n",
">>> my_generator = (letter for letter in 'abcdefg')\n",
">>> next(my_generator)\n",
"'a'\n",
">>> my_generator.next()\n",
"Traceback (most recent call last):\n",
" File \"<stdin>\", line 1, in <module>\n",
"AttributeError: 'generator' object has no attribute 'next'"
],
"language": "python",
"metadata": {},
"outputs": []