Many beginning Python users are wondering with which version of Python they should start. My answer to this question is usually something along the lines 'just go with the version your favorite tutorial was written in, and check out the differences later on.'
But what if you are starting a new project and have the choice to pick? I would say there is currently no 'right' or 'wrong' as long as both Python 2.7.x and Python 3.x support the libraries that you are planning to use. However, it is worthwhile to have a look at the major differences between those two most popular versions of Python to avoid common pitfalls when writing the code for either one of them, or if you are planning to port your project.
Sections
- The print function
- Integer division
- Unicode
- xrange
- The
__contains__
method forrange
objects in Python 3
- The
- Raising exceptions
- Handling exceptions
- The next() function and .next() method
- For-loop variables and the global namespace leak
- Comparing unorderable types
- Parsing user inputs via input()
- Returning iterable objects instead of lists
- Banker's Rounding
The __future__
module
Python 3.x introduced some Python 2-incompatible keywords and features that can be imported via the in-built __future__
module in Python 2. It is recommended to use __future__
imports it if you are planning Python 3.x support for your code. For example, if we want Python 3.x's integer division behavior in Python 2, we can import it via
More features that can be imported from the __future__
module are listed in the table below:
Python is a very popular general-purpose programming language which was created by Guido van Rossum, and released in 1991. It is open-source and you can freely use & distribute Python, even for commercial use. It is very popular for web development and you can build almost anything like mobile apps, web apps, tools, data analytics, machine. First, you can set up a shell alias: alias python=/usr/local/bin/python2.7 Type that at a prompt, or put it in your /.bashrc if you want the change to be persistent, and now when you type python it runs your chosen 2.7, but when some program on your system tries to run a script with /usr/bin/env python.
feature | optional in | mandatory in | effect |
---|---|---|---|
nested_scopes | 2.1.0b1 | 2.2 | PEP 227:Statically Nested Scopes |
generators | 2.2.0a1 | 2.3 | PEP 255:Simple Generators |
division | 2.2.0a2 | 3.0 | PEP 238:Changing the Division Operator |
absolute_import | 2.5.0a1 | 3.0 | PEP 328:Imports: Multi-Line and Absolute/Relative |
with_statement | 2.5.0a1 | 2.6 | PEP 343:The 'with' Statement |
print_function | 2.6.0a2 | 3.0 | PEP 3105:Make print a function |
unicode_literals | 2.6.0a2 | 3.0 | PEP 3112:Bytes literals in Python 3000 |
The print function
Very trivial, and the change in the print-syntax is probably the most widely known change, but still it is worth mentioning: Python 2's print statement has been replaced by the print()
function, meaning that we have to wrap the object that we want to print in parantheses.
Python 2 doesn't have a problem with additional parantheses, but in contrast, Python 3 would raise a SyntaxError
if we called the print function the Python 2-way without the parentheses.
Python 2
Python 3
Note:
Printing 'Hello, World' above via Python 2 looked quite 'normal'. However, if we have multiple objects inside the parantheses, we will create a tuple, since print
is a 'statement' in Python 2, not a function call.
Integer division
This change is particularly dangerous if you are porting code, or if you are executing Python 3 code in Python 2, since the change in integer-division behavior can often go unnoticed (it doesn't raise a SyntaxError
).
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 (and vice versa, I recommend a from __future__ import division
in your Python 2 scripts).
Python 2
Python 3
Unicode
Python 2 has ASCII str()
types, separate unicode()
, but no byte
type.
Now, in Python 3, we finally have Unicode (utf-8) str
ings, and 2 byte classes: byte
and bytearray
s.
Python 2
Python 3
xrange
The usage of xrange()
is very popular in Python 2.x for creating an iterable object, e.g., in a for-loop or list/set-dictionary-comprehension.
The behavior was quite similar to a generator (i.e., 'lazy evaluation'), but here the xrange-iterable is not exhaustible - meaning, you could iterate over it infinitely.
Thanks to its 'lazy-evaluation', the advantage of the regular range()
is that xrange()
is generally faster if you have to iterate over it only once (e.g., in a for-loop). However, in contrast to 1-time iterations, it is not recommended if you repeat the iteration 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 (xrange()
raises a NameError
in Python 3).
Python 2
Python 3
The __contains__
method for range
objects in Python 3
Another thing worth mentioning is that range
got a 'new' __contains__
method in Python 3.x (thanks to Yuchen Ying, who pointed this out). The __contains__
method can speedup 'look-ups' in Python 3.x range
significantly for integer and Boolean types.
Based on the timeit
results above, you see that the execution for the 'look up' was about 60,000 faster when it was of an integer type rather than a float. However, since Python 2.x's range
or xrange
doesn't have a __contains__
method, the 'look-up speed' wouldn't be that much different for integers or floats:
Below the 'proofs' that the __contain__
method wasn't added to Python 2.x yet:
Note about the speed differences in Python 2 and 3
Some people pointed out the speed difference between Python 3's range()
and Python2's xrange()
. Since they are implemented the same way one would expect the same speed. However the difference here just comes from the fact that Python 3 generally tends to run slower than Python 2.
Raising exceptions
Where Python 2 accepts both notations, the ‘old' and the ‘new' syntax, Python 3 chokes (and raises a SyntaxError
in turn) if we don't enclose the exception argument in parentheses:
Python 2
Python 3
The proper way to raise an exception in Python 3:
Handling exceptions
Also the handling of exceptions has slightly changed in Python 3. In Python 3 we have to use the 'as
' keyword now
Python 2
Python 3
The next() function and .next() method
Since next()
(.next()
) is such a commonly used function (method), this is another syntax change (or rather change in implementation) that is worth mentioning: where you can use both the function and method syntax in Python 2.7.5, the next()
function is all that remains in Python 3 (calling the .next()
method raises an AttributeError
).
Python 2
Python 3
For-loop variables and the global namespace leak
Good news is: In Python 3.x for-loop variables don't leak into the global namespace anymore!
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.'
Python 2
Python 3
Comparing unorderable types
Another nice change in Python 3 is that a TypeError
is raised as warning if we try to compare unorderable types.
Python 2
Python 3
Parsing user inputs via input()
Fortunately, the input()
function was fixed in Python 3 so that it always stores the user inputs as str
objects. In order to avoid the dangerous behavior in Python 2 to read in other types than strings
, we have to use raw_input()
instead.
Python 2
Python 3
Returning iterable objects instead of lists
As we have already seen in the xrange
section, some functions and methods return iterable objects in Python 3 now - instead of lists in Python 2.
Since we usually iterate over those only once anyway, I think this change makes a lot of sense to save memory. However, it is also possible - in contrast to generators - to iterate over those multiple times if needed, it is only not so efficient.
And for those cases where we really need the list
-objects, we can simply convert the iterable object into a list
via the list()
function.
Python 2
Python 3
Some more commonly used functions and methods that don't return lists anymore in Python 3:
zip()
map()
filter()
dictionary's
.keys()
methoddictionary's
.values()
methoddictionary's
.items()
method
Banker's Rounding
Python 3 adopted the now standard way of rounding decimals when it results in a tie (.5) at the last significant digits. Now, in Python 3, decimals are rounded to the nearest even number. Although it's an inconvenience for code portability, it's supposedly a better way of rounding compared to rounding up as it avoids the bias towards large numbers. For more information, see the excellent Wikipedia articles and paragraphs:
Python 2
Python 3
More articles about Python 2 and Python 3
Here is a list of some good articles concerning Python 2 and 3 that I would recommend as a follow-up.
// Porting to Python 3
// Pro and anti Python 3
Release Date: Dec. 24, 2018
Python 3.7.2 was the second bugfix release of Python 3.7.
There are now newer bugfix releases of Python 3.7 that supersede 3.7.2 and Python 3.8 is now the latest feature release of Python 3. Get the latest releases of 3.7.x and 3.8.x here. We plan to continue to provide bugfix releasesfor 3.7.x until mid 2020 and security fixes until mid 2023.
Among the major new features in Python 3.7 are:
- PEP 539, new C API for thread-local storage
- PEP 545, Python documentation translations
- New documentation translations: Japanese,French, andKorean.
- PEP 552, Deterministic pyc files
- PEP 553, Built-in breakpoint()
- PEP 557, Data Classes
- PEP 560, Core support for typing module and generic types
- PEP 562, Customization of access to module attributes
- PEP 563, Postponed evaluation of annotations
- PEP 564, Time functions with nanosecond resolution
- PEP 565, Improved DeprecationWarning handling
- PEP 567, Context Variables
- Avoiding the use of ASCII as a default text encoding (PEP 538, legacy C locale coercionand PEP 540, forced UTF-8 runtime mode)
- The insertion-order preservation nature of dict objects is now an official part of the Python language spec.
- Notable performance improvements in many areas.
Please see What's New In Python 3.7 for more information.
- PEP 537, 3.7 Release Schedule
- Report bugs at https://bugs.python.org.
- Help fund Python and its community.
Thonny Python 2.7 Software
Unicode
Python 2 has ASCII str()
types, separate unicode()
, but no byte
type.
Now, in Python 3, we finally have Unicode (utf-8) str
ings, and 2 byte classes: byte
and bytearray
s.
Python 2
Python 3
xrange
The usage of xrange()
is very popular in Python 2.x for creating an iterable object, e.g., in a for-loop or list/set-dictionary-comprehension.
The behavior was quite similar to a generator (i.e., 'lazy evaluation'), but here the xrange-iterable is not exhaustible - meaning, you could iterate over it infinitely.
Thanks to its 'lazy-evaluation', the advantage of the regular range()
is that xrange()
is generally faster if you have to iterate over it only once (e.g., in a for-loop). However, in contrast to 1-time iterations, it is not recommended if you repeat the iteration 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 (xrange()
raises a NameError
in Python 3).
Python 2
Python 3
The __contains__
method for range
objects in Python 3
Another thing worth mentioning is that range
got a 'new' __contains__
method in Python 3.x (thanks to Yuchen Ying, who pointed this out). The __contains__
method can speedup 'look-ups' in Python 3.x range
significantly for integer and Boolean types.
Based on the timeit
results above, you see that the execution for the 'look up' was about 60,000 faster when it was of an integer type rather than a float. However, since Python 2.x's range
or xrange
doesn't have a __contains__
method, the 'look-up speed' wouldn't be that much different for integers or floats:
Below the 'proofs' that the __contain__
method wasn't added to Python 2.x yet:
Note about the speed differences in Python 2 and 3
Some people pointed out the speed difference between Python 3's range()
and Python2's xrange()
. Since they are implemented the same way one would expect the same speed. However the difference here just comes from the fact that Python 3 generally tends to run slower than Python 2.
Raising exceptions
Where Python 2 accepts both notations, the ‘old' and the ‘new' syntax, Python 3 chokes (and raises a SyntaxError
in turn) if we don't enclose the exception argument in parentheses:
Python 2
Python 3
The proper way to raise an exception in Python 3:
Handling exceptions
Also the handling of exceptions has slightly changed in Python 3. In Python 3 we have to use the 'as
' keyword now
Python 2
Python 3
The next() function and .next() method
Since next()
(.next()
) is such a commonly used function (method), this is another syntax change (or rather change in implementation) that is worth mentioning: where you can use both the function and method syntax in Python 2.7.5, the next()
function is all that remains in Python 3 (calling the .next()
method raises an AttributeError
).
Python 2
Python 3
For-loop variables and the global namespace leak
Good news is: In Python 3.x for-loop variables don't leak into the global namespace anymore!
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.'
Python 2
Python 3
Comparing unorderable types
Another nice change in Python 3 is that a TypeError
is raised as warning if we try to compare unorderable types.
Python 2
Python 3
Parsing user inputs via input()
Fortunately, the input()
function was fixed in Python 3 so that it always stores the user inputs as str
objects. In order to avoid the dangerous behavior in Python 2 to read in other types than strings
, we have to use raw_input()
instead.
Python 2
Python 3
Returning iterable objects instead of lists
As we have already seen in the xrange
section, some functions and methods return iterable objects in Python 3 now - instead of lists in Python 2.
Since we usually iterate over those only once anyway, I think this change makes a lot of sense to save memory. However, it is also possible - in contrast to generators - to iterate over those multiple times if needed, it is only not so efficient.
And for those cases where we really need the list
-objects, we can simply convert the iterable object into a list
via the list()
function.
Python 2
Python 3
Some more commonly used functions and methods that don't return lists anymore in Python 3:
zip()
map()
filter()
dictionary's
.keys()
methoddictionary's
.values()
methoddictionary's
.items()
method
Banker's Rounding
Python 3 adopted the now standard way of rounding decimals when it results in a tie (.5) at the last significant digits. Now, in Python 3, decimals are rounded to the nearest even number. Although it's an inconvenience for code portability, it's supposedly a better way of rounding compared to rounding up as it avoids the bias towards large numbers. For more information, see the excellent Wikipedia articles and paragraphs:
Python 2
Python 3
More articles about Python 2 and Python 3
Here is a list of some good articles concerning Python 2 and 3 that I would recommend as a follow-up.
// Porting to Python 3
// Pro and anti Python 3
Release Date: Dec. 24, 2018
Python 3.7.2 was the second bugfix release of Python 3.7.
There are now newer bugfix releases of Python 3.7 that supersede 3.7.2 and Python 3.8 is now the latest feature release of Python 3. Get the latest releases of 3.7.x and 3.8.x here. We plan to continue to provide bugfix releasesfor 3.7.x until mid 2020 and security fixes until mid 2023.
Among the major new features in Python 3.7 are:
- PEP 539, new C API for thread-local storage
- PEP 545, Python documentation translations
- New documentation translations: Japanese,French, andKorean.
- PEP 552, Deterministic pyc files
- PEP 553, Built-in breakpoint()
- PEP 557, Data Classes
- PEP 560, Core support for typing module and generic types
- PEP 562, Customization of access to module attributes
- PEP 563, Postponed evaluation of annotations
- PEP 564, Time functions with nanosecond resolution
- PEP 565, Improved DeprecationWarning handling
- PEP 567, Context Variables
- Avoiding the use of ASCII as a default text encoding (PEP 538, legacy C locale coercionand PEP 540, forced UTF-8 runtime mode)
- The insertion-order preservation nature of dict objects is now an official part of the Python language spec.
- Notable performance improvements in many areas.
Please see What's New In Python 3.7 for more information.
- PEP 537, 3.7 Release Schedule
- Report bugs at https://bugs.python.org.
- Help fund Python and its community.
Thonny Python 2.7 Software
Thonny Python 2.7 Download
- The binaries for AMD64 will also work on processors that implement the Intel 64 architecture. (Also known as the 'x64' architecture, and formerly known as both 'EM64T' and 'x86-64'.)
- There are now 'web-based' installers for Windows platforms; the installer will download the needed software components at installation time.
- There are redistributable zip files containing the Windows builds, making it easy to redistribute Python as part of another software package. Please see the documentation regarding Embedded Distribution for more information.
- UPDATED 2019-01-09: An issue was discovered in the embeddable packages for Windows and updated download files have been provided for the Windows x86-64 embeddable zip file and the Windows x86 embeddable zip file and their GPG signatures. No other download was affected. See https://bugs.python.org/issue35596 for more information.
- For Python 3.7 releases, we provide two binary installer options for download. The default variant is 64-bit-only and works on macOS 10.9 (Mavericks) and later systems. We also continue to provide a 64-bit/32-bit variant that works on all versions of macOS from 10.6 (Snow Leopard) on. Both variants now come with batteries-included versions oF Tcl/Tk 8.6 for users of IDLE and other tkinter-based GUI applications; third-party and system versions of Tcl/Tk are no longer used. Consider using the newer 10.9 64-bit-only installer variant, unless you are building Python applications that also need to work on older macOS systems.
- Both python.org installer variants include private copies of OpenSSL 1.1.0. Please carefully read the Important Information displayed during installation for information about SSL/TLS certificate validation and the Install Certificates.command.
Raspberry Pi Thonny Python 2.7
Version | Operating System | Description | MD5 Sum | File Size | GPG |
---|---|---|---|---|---|
Gzipped source tarball | Source release | 02a75015f7cd845e27b85192bb0ca4cb | 22897802 | SIG | |
XZ compressed source tarball | Source release | df6ec36011808205beda239c72f947cb | 17042320 | SIG | |
macOS 64-bit/32-bit installer | Mac OS X | for Mac OS X 10.6 and later | d8ff07973bc9c009de80c269fd7efcca | 34405674 | SIG |
macOS 64-bit installer | Mac OS X | for OS X 10.9 and later | 0fc95e9f6d6b4881f3b499da338a9a80 | 27766090 | SIG |
Windows help file | Windows | 941b7d6279c0d4060a927a65dcab88c4 | 8092167 | SIG | |
Windows x86-64 embeddable zip file | Windows | for AMD64/EM64T/x64 | f81568590bef56e5997e63b434664d58 | 7025085 | SIG |
Windows x86-64 executable installer | Windows | for AMD64/EM64T/x64 | ff258093f0b3953c886192dec9f52763 | 26140976 | SIG |
Windows x86-64 web-based installer | Windows | for AMD64/EM64T/x64 | 8de2335249d84fe1eeb61ec25858bd82 | 1362888 | SIG |
Windows x86 embeddable zip file | Windows | 26881045297dc1883a1d61baffeecaf0 | 6533256 | SIG | |
Windows x86 executable installer | Windows | 38156b62c0cbcb03bfddeb86e66c3a0f | 25365744 | SIG | |
Windows x86 web-based installer | Windows | 1e6c626514b72e21008f8cd53f945f10 | 1324648 | SIG |