Differences between Python 2.x and 3.x Versions
Python's 3.0 version, often referred to as Python 3000, or simply Py3k, represents a significant upgrade compared to earlier versions of Python.
To avoid unnecessary complications, Python 3.0 was designed without backward compatibility in mind.
Many programs designed for earlier Python versions do not run correctly on Python 3.0.
To accommodate existing programs, Python 2.6 served as a transitional version, maintaining the syntax and libraries of Python 2.x while also considering migration to Python 3.0, allowing the use of some Python 3.0 syntax and functions.
New Python programs are recommended to use the syntax of Python 3.0.
Unless the execution environment cannot install Python 3.0 or the program itself uses third-party libraries that do not support Python 3.0, such as Twisted, py2exe, and PIL.
Most third-party libraries are actively working to be compatible with Python 3.0. Even if Python 3.0 cannot be used immediately, it is advisable to write programs compatible with Python 3.0 and execute them using Python 2.6 or Python 2.7.
The changes in Python 3.0 are mainly in the following areas:
print Function
The print statement has been replaced with the print()
function. Python 2.6 and Python 2.7 partially support this new print syntax. In Python 2.6 and Python 2.7, the following three forms are equivalent:
print "fish"
print ("fish") # Note the space after print
print("fish") # print() cannot have any other parameters
However, Python 2.6 actually already supports the new print() syntax, as shown in the example below:
from __future__ import print_function
print("fish", "panda", sep=', ')
If you want to use the print function from Python 3.x in a Python 2.x version, you can import the __future__
package, which disables the print statement from Python 2.x and adopts the print function from Python 3.x:
Example
>>> list = ["a", "b", "c"]
>>> print list # Python 2.x print statement
['a', 'b', 'c']
>>> from __future__ import print_function # Import the __future__ package
>>> print list # Python 2.x print statement is disabled, causes an error
File "<stdin>", line 1
print list
^
SyntaxError: invalid syntax
>>> print (list) # Use the Python 3.x print function
['a', 'b', 'c']
>>>
Many compatibility features between Python 3.x and Python 2.x can be imported using the __future__
package.
Unicode
Python 2 has an ASCII str() type, with unicode() being separate and not a byte type.
Now, in Python 3, we finally have Unicode (utf-8) strings, and a byte class: byte and bytearrays.
Since Python 3.x source files default to using utf-8 encoding, using Chinese characters is more convenient:
>>> 中国 = 'china'
>>> print(中国)
china
Python 2.x
>>> str = "我爱北京天安门"
>>> str
'\xe6\x88\x91\xe7\x88\xb1\xe5\x8c\x97\xe4\xba\xac\xe5\xa4\xa9\xe5\xae\x89\xe9\x97\xa8'
>>> str = u"我爱北京天安门"
>>> str
u'\u6211\u7231\u5317\u4eac\u5929\u5b89\u95e8'
Python 3.x
>>> str = "我爱北京天安门"
>>> str
'我爱北京天安门'
Division Operation
Python's division is more advanced than other languages, with complex rules. Python has two division operators, /
and //
.
First, let's discuss the /
division:
English:
In Python 2.x, the /
division behaves like most languages we are familiar with, such as Java and C; the result of integer division is an integer, completely ignoring the fractional part, while floating-point division retains the decimal part to yield a floating-point result.
In Python 3.x, the /
division no longer behaves this way; division between integers also results in a floating-point number.
Python 2.x:
>>> 1 / 2
0
>>> 1.0 / 2.0
0.5
Python 3.x:
>>> 1/2
0.5
For the //
division, this type of division is called floor division, which automatically performs a floor operation on the result of the division. This behavior is consistent in both Python 2.x and Python 3.x.
Python 2.x:
>>> -1 // 2
-1
Python 3.x:
>>> -1 // 2
-1
Note that it does not simply truncate the fractional part but performs a floor operation. If you need to truncate to an integer, you should use the trunc
function from the math
module.
Python 3.x:
>>> import math
>>> math.trunc(1 / 2)
0
>>> math.trunc(-1 / 2)
0
Exceptions
Handling exceptions has also been slightly changed in Python 3; we now use as
as a keyword.
The syntax for catching exceptions has changed from except exc, var
to except exc as var
.
The syntax except (exc1, exc2) as var
can be used to catch multiple types of exceptions. Python 2.6 already supports these syntaxes.
- In Python 2.x, all types of objects could be thrown directly, but in Python 3.x, only objects that inherit from
BaseException
can be thrown.
- In Python 2.x, all types of objects could be thrown directly, but in Python 3.x, only objects that inherit from
- In Python 2.x, the
raise
statement used a comma to separate the thrown object type and its arguments, but Python 3.x has eliminated this unusual syntax, allowing direct invocation of the constructor to throw the object.
- In Python 2.x, the
In Python 2.x, exceptions were often used for purposes other than just indicating program errors, sometimes even for control flow. In Python 3.x, it is evident that the designers have made exceptions more focused, intended only for use when errors occur.
xrange
In Python 2, the use of xrange()
to create iterable objects was very popular, such as in for
loops or list/set/dictionary comprehensions.
This behavior is very similar to that of generators (e.g., "lazy evaluation"). However, the xrange
iterable is infinite, meaning you can iterate over it indefinitely.
Due to its lazy evaluation, if you need to iterate over it only once, the xrange()
function is faster than range()
(e.g., in for
loops). Nevertheless, it is not recommended to iterate over it multiple times, as the generator starts from the beginning each time.
In Python 3, range()
is implemented like xrange()
in Python 2, so a dedicated xrange()
function no longer exists (calling xrange()
in Python 3 raises a NameError
).
import timeit
n = 10000
def test_range(n):
for i in range(n):
pass
def test_xrange(n):
for i in xrange(n):
pass
Python 2:
print 'Python', python_version()
print '\ntiming range()'
%timeit test_range(n)
print '\n\ntiming xrange()'
%timeit test_xrange(n)
Python 2.7.6
timing range()
1000 loops, best of 3: 433 µs per loop
timing xrange()
1000 loops, best of 3: 350 µs per loop
Python 3:
print('Python', python_version())
print('\ntiming range()')
%timeit test_range(n)
Python 3.4.1
timing range()
1000 loops, best of 3: 520 µs per loop
print(xrange(10))
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-5-5d8f9b79ea70> in <module>()
1 print(range(10))
NameError: name 'xrange' is not defined
Octal Literal Representation
Octal numbers must be written as 0o777, the old form 0777 is no longer valid; binary must be written as 0b111.
A new bin() function has been added to convert an integer to a binary string. Python 2.6 already supports these syntaxes.
In Python 3.x, there is only one way to represent octal literals, which is 0o1000.
python 2.x
>>> 0o1000
512
>>> 01000
512
python 3.x
>>> 01000
File "<stdin>", line 1
01000
^
SyntaxError: invalid token
>>> 0o1000
512
Inequality Operator
In Python 2.x, inequality could be written in two ways: != and <>.
In Python 3.x, the <> notation has been removed, leaving only !=. Fortunately, I never had the habit of using <>.
Removal of the repr Expression ``
In Python 2.x, backticks `` were equivalent to the repr function.
In Python 3.x, the use of `` has been removed, allowing only the repr function. The intention was to make the code clearer. However, I feel that repr is rarely used, typically only during debugging, and most of the time, the str function is used to describe objects as strings.
def sendMail(from_: str, to: str, title: str, body: str) -> bool:
pass
Renaming of Multiple Modules (according to PEP8)
Old Name | New Name |
---|---|
_winreg | winreg |
ConfigParser | configparser |
copy_reg | copyreg |
Queue | queue |
SocketServer | socketserver |
repr | reprlib |
The StringIO module has been merged into the new io module. Modules like new, md5, gopherlib, etc., have been removed. Python 2.6 already supports the new io module.
httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, cookielib have been merged into the http package.
The exec statement has been removed, leaving only the exec() function. Python 2.6 already supports the exec() function.
5. Data Types
1) In Py3.X, the long type has been removed; there is now only one integer type—int, which behaves like the long type in 2.X.
2) A new bytes type has been added, corresponding to the 8-bit strings in 2.X. A bytes literal can be defined as follows:
>>> b = b'china'
>>> type(b)
<type 'bytes'>
str objects and bytes objects can be converted to each other using .encode() (str -> bytes) or .decode() (bytes -> str) methods.
>>> s = b.decode()
>>> s
'china'
>>> b1 = s.encode()
>>> b1
b'china'
3) The .keys(), .items(), and .values() methods of dict return iterators, and the previous iterkeys() and other similar functions have been deprecated. Also removed is dict.has_key(), use in instead.