mirror of
https://github.com/rasbt/python_reference.git
synced 2024-11-27 22:11:13 +00:00
diff python 2 and 3
This commit is contained in:
parent
997a60f6b0
commit
215228201d
|
@ -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": []
|
||||
|
|
|
@ -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": []
|
||||
|
|
Loading…
Reference in New Issue
Block a user