From f81049e1ac3881ea46ffc42b645efde9f6b511e9 Mon Sep 17 00:00:00 2001 From: rasbt Date: Sat, 24 May 2014 12:05:09 -0400 Subject: [PATCH] html version --- README.md | 2 +- ...ey_differences_between_python_2_and_3.html | 632 ++++++++++++++++++ 2 files changed, 633 insertions(+), 1 deletion(-) create mode 100644 tutorials/key_differences_between_python_2_and_3.html diff --git a/README.md b/README.md index db00ca9..feebdc1 100755 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ A collection of useful scripts, tutorials, and other Python-related things - Python's scope resolution for variable names and the LEGB rule [[IPython nb](http://nbviewer.ipython.org/github/rasbt/python_reference/blob/master/tutorials/scope_resolution_legb_rule.ipynb?create=1)] -- Key differences between Python 2.x and Python 3.x [[Markdown](./tutorials/key_differences_python2_python3.md)] +- Key differences between Python 2.x and Python 3.x [[HTML](http://htmlpreview.github.io/?https://github.com/rasbt/python_reference/blob/master/tutorials/key_differences_between_python_2_and_3.html)] - A thorough guide to SQLite database operations in Python [[Markdown](./sqlite3_howto/README.md)] diff --git a/tutorials/key_differences_between_python_2_and_3.html b/tutorials/key_differences_between_python_2_and_3.html new file mode 100644 index 0000000..431d7c9 --- /dev/null +++ b/tutorials/key_differences_between_python_2_and_3.html @@ -0,0 +1,632 @@ + + + + + + +Key differences between Python 2 and 3 + + + +

Sebastian Raschka
+last updated: 05/24/2014

+ +


+ +

This is a subsection of "A collection of not-so-obvious Python stuff you should know!"

+ +

+ +


+ +

Key differences between Python 2 and 3

+ +


+ +

There are some good articles already that are summarizing the differences between Python 2 and 3, e.g.,
+- https://wiki.python.org/moin/Python2orPython3 +- https://docs.python.org/3.0/whatsnew/3.0.html +- http://python3porting.com/differences.html +- https://docs.python.org/3/howto/pyporting.html
+etc.

+ +

But it might be still worthwhile, especially for Python newcomers, to take a look at some of those! +(Note: the the code was executed in Python 3.4.0 and Python 2.7.5 and copied from interactive shell sessions.)

+ +

+ +


+ +

Overview - Key differences between Python 2 and 3

+ + + + +


+

+ +

+
+

+ +

Unicode...

+ +

[back to Python 2.x vs 3.x overview]

+ +

- Python 2:

+ +

We have ASCII str() types, separate unicode(), but no byte type

+ +

- Python 3:

+ +

Now, we finally have Unicode (utf-8) strings, and 2 byte classes: byte and bytearrays

+ +


+ + + + +
#############
+# Python 2
+#############
+
+>>> type(unicode('is like a python3 str()'))
+<type 'unicode'>
+
+>>> type(b'byte type does not exist')
+<type 'str'>
+
+>>> 'they are really' + b' the same'
+'they are really the same'
+
+>>> type(bytearray(b'bytearray oddly does exist though'))
+<type 'bytearray'>
+
+#############
+# Python 3
+#############
+
+>>> print('strings are now utf-8 \u03BCnico\u0394é!')
+strings are now utf-8 μnicoΔé!
+
+
+>>> type(b' and we have byte types for storing data')
+<class 'bytes'>
+
+>>> type(bytearray(b'but also bytearrays for those who prefer them over strings'))
+<class 'bytearray'>
+
+>>> 'string' + b'bytes for data'
+Traceback (most recent call last):s
+  File "<stdin>", line 1, in <module>
+TypeError: Can't convert 'bytes' object to str implicitly
+
+ + +

+
+

+ +

The print statement

+ +

[back to Python 2.x vs 3.x overview]

+ +

Very trivial, but this change makes sense, Python 3 now only accepts prints with proper parentheses - just like the other function calls ...

+ +


+ + + + +
# Python 2
+>>> print 'Hello, World!'
+Hello, World!
+>>> print('Hello, World!')
+Hello, World!
+
+# Python 3
+>>> print('Hello, World!')
+Hello, World!
+>>> print 'Hello, World!'
+  File "<stdin>", line 1
+    print 'Hello, World!'
+                        ^
+SyntaxError: invalid syntax
+
+ + +


+ +

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:

+ +


+ + + + +
# Python 2
+>>> print "line 1", ; print 'same line'
+line 1 same line
+
+# Python 3
+>>> print("line 1", end="") ; print (" same line")
+line 1 same line
+
+ + +

+
+

+ +

Integer division

+ +

[back to Python 2.x vs 3.x overview]

+ +

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.
+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).

+ +


+ + + + +
# Python 2
+>>> 3 / 2
+1
+>>> 3 // 2
+1
+>>> 3 / 2.0
+1.5
+>>> 3 // 2.0
+1.0
+
+# Python 3
+>>> 3 / 2
+1.5
+>>> 3 // 2
+1
+>>> 3 / 2.0
+1.5
+>>> 3 // 2.0
+1.0
+
+ + +

+
+

+ +

xrange()

+ +

[back to Python 2.x vs 3.x overview]

+ +

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!
+In Python 3, the range() was implemented like the xrange() function so that a dedicated xrange() function does not exist anymore.

+ + + + +
# Python 2
+> python -m timeit 'for i in range(1000000):' ' pass'
+10 loops, best of 3: 66 msec per loop
+
+    > python -m timeit 'for i in xrange(1000000):' ' pass'
+10 loops, best of 3: 27.8 msec per loop
+
+# Python 3
+> python3 -m timeit 'for i in range(1000000):' ' pass'
+10 loops, best of 3: 51.1 msec per loop
+
+> python3 -m timeit 'for i in xrange(1000000):' ' pass'
+Traceback (most recent call last):
+  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/timeit.py", line 292, in main
+    x = t.timeit(number)
+  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/timeit.py", line 178, in timeit
+    timing = self.inner(it, self.timer)
+  File "<timeit-src>", line 6, in inner
+    for i in xrange(1000000):
+NameError: name 'xrange' is not defined
+
+ + +

+
+

+ +

Raising exceptions

+ +

[back to Python 2.x vs 3.x overview]

+ +

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:

+ +


+ + + + +
# Python 2
+>>> raise IOError, "file error"
+Traceback (most recent call last):
+  File "<stdin>", line 1, in <module>
+IOError: file error
+>>> raise IOError("file error")
+Traceback (most recent call last):
+  File "<stdin>", line 1, in <module>
+IOError: file error
+
+    
+# Python 3    
+>>> raise IOError, "file error"
+  File "<stdin>", line 1
+    raise IOError, "file error"
+                 ^
+SyntaxError: invalid syntax
+>>> raise IOError("file error")
+Traceback (most recent call last):
+  File "<stdin>", line 1, in <module>
+OSError: file error
+
+ + +

+
+

+ +

Handling exceptions

+ +

[back to Python 2.x vs 3.x overview]

+ +

Also the handling of exceptions has slightly changed in Python 3. Now, we have to use the as keyword!

+ + + + +
# Python 2
+>>> try:
+...     blabla
+... except NameError, err:
+...     print err, '--> our error msg'
+... 
+name 'blabla' is not defined --> our error msg
+
+# Python 3
+>>> try:
+...     blabla
+... except NameError as err:
+...     print(err, '--> our error msg')
+... 
+name 'blabla' is not defined --> our error msg
+
+ + +

+
+

+ +

The next() function and .next() method

+ +

[back to Python 2.x vs 3.x overview]

+ +

Where you can use both function and method in Python 2.7.5, the next() function is all that remain in Python 3!

+ + + + +
# Python 2
+>>> my_generator = (letter for letter in 'abcdefg')
+>>> my_generator.next()
+'a'
+>>> next(my_generator)
+'b'
+
+# Python 3
+>>> my_generator = (letter for letter in 'abcdefg')
+>>> next(my_generator)
+'a'
+>>> my_generator.next()
+Traceback (most recent call last):
+  File "<stdin>", line 1, in <module>
+AttributeError: 'generator' object has no attribute 'next'
+
+ + +

+
+

+ +

In Python 3.x for-loop variables don't leak into the global namespace anymore

+ +

[back to Python 2.x vs 3.x overview]

+ +

This goes back to a change that was made in Python 3.x and is described in What’s New In Python 3.0 as follows:

+ +

"List comprehensions no longer support the syntactic form [... for var in item1, item2, ...]. Use [... for var in (item1, item2, ...)] instead. Also note that list comprehensions have different semantics: they are closer to syntactic sugar for a generator expression inside a list() constructor, and in particular the loop control variables are no longer leaked into the surrounding scope."

+ +


+[In:]

+ + + + +
from platform import python_version
+print('This code cell was executed in Python', python_version())
+
+i = 1
+print([i for i in range(5)])
+print(i, '-> i in global')
+
+ + +


+[Out:]

+ + + + +
This code cell was executed in Python 3.3.5
+[0, 1, 2, 3, 4]
+1 -> i in global
+
+ + +


+
+
+[In:]

+ + + + +
from platform import python_version
+print 'This code cell was executed in Python', python_version()
+
+i = 1
+print [i for i in range(5)]
+print i, '-> i in global' 
+
+ + +


+[Out:]

+ + + + +
This code cell was executed in Python 2.7.6
+[0, 1, 2, 3, 4]
+4 -> i in global
+
+ + +

+
+

+ +

Python 3.x prevents us from comparing unorderable types

+ +

[back to Python 2.x vs 3.x overview]

+ +


+[In:]

+ + + + +
from platform import python_version
+print 'This code cell was executed in Python', python_version()
+
+print [1, 2] > 'foo'
+print (1, 2) > 'foo'
+print [1, 2] > (1, 2)
+
+ + +


+[Out:]

+ + + + +
This code cell was executed in Python 2.7.6
+False
+True
+False
+
+ + +


+
+

+ +

[In:]

+ + + + +
from platform import python_version
+print('This code cell was executed in Python', python_version())
+
+print([1, 2] > 'foo')
+print((1, 2) > 'foo')
+print([1, 2] > (1, 2))
+
+ + +

[Out:]

+ + + + +
This code cell was executed in Python 3.3.5
+---------------------------------------------------------------------------
+TypeError                                 Traceback (most recent call last)
+<ipython-input-3-1d774c677f73> in <module>()
+      2 print('This code cell was executed in Python', python_version())
+      3 
+----> 4 [1, 2] > 'foo'
+      5 (1, 2) > 'foo'
+      6 [1, 2] > (1, 2)
+
+TypeError: unorderable types: list() > str()
+
+ + + \ No newline at end of file