Differences between Python 2.x and 3.x
<strong>Differences between Python 2.x and 3.x</strong>
Python version 3.0, often referred to as Python 3000, or Py3k for short, is a significant upgrade compared to earlier versions of Python.
To avoid excessive redundancy, Python 3.0 was not designed with backward compatibility in mind.
Many programs designed for earlier Python versions will not run properly on Python 3.0.
To accommodate existing programs, Python 2.6 is a transitional version that largely uses Python 2.x syntax and libraries, while also allowing for migration to Python 3.0 and allowing for the use of some Python 3.0 syntax and functions.
New Python programs are recommended to use Python 3.0 syntax.
Unless your runtime environment cannot install Python 3.0 or your program uses third-party libraries that do not support Python 3.0. Currently, third-party libraries that do not support Python 3.0 include Twisted, py2exe, and PIL.
Most third-party libraries are working to become compatible with Python 3.0. Even if you cannot use Python 3.0 immediately, it is recommended to write programs that are compatible with Python 3.0 and then run them using Python 2.6 or Python 2.7.
The main changes in Python 3.0 are as follows:
print Function
The print statement is gone, replaced by the print() function. Python 2.6 and Python 2.7 partially support this form of print syntax. In Python 2.6 and Python 2.7, the following three forms are equivalent:
print (“fish”) #Note the space after print
print (“fish”) #print() cannot take any other arguments
However, Python 2.6 actually supports the new print() syntax:
from __future__ import print_function
print (“fish”, “panda”, sep=’, ‘)
Unicode
Python 2 had the ASCII str() type, and unicode() was a separate, non-byte type.
Now, in Python 3, we finally have Unicode (UTF-8) strings, as well as a bytes class: byte and bytearrays.
Since Python 3.x source code files use UTF-8 encoding by default, the following code is legal:
>>> China = 'china'
>>>print(中国)
china
Python 2.x
>>> str = "I love Beijing Tiananmen"
>>> str
'xe6x88x91xe7x88xb1xe5x8cx97xe4xbaxacxe5xa4xa9xe5xaex89xe9x97xa8'
>>> str = u"I love Beijing Tiananmen"
>>> str
u'u6211u7231u5317u4eacu5929u5b89u95e8'
Python 3.x
>>> str = "I love Beijing Tiananmen"
>>> str
'I love Beijing Tiananmen'
Division Operation
Division in Python is much more advanced than in other languages, with complex rules. Python has two division operators: / and //.
First, let’s talk about / division:
In Python 2.x, / division is similar to what we’re familiar with in most languages, such as Java and C. Integer division results in an integer, completely ignoring the decimal point. Floating-point division retains the decimal point, resulting in a floating-point result.
In Python 3.x, the / division method no longer behaves this way. Integer division will also result in a floating-point number.
Python 2.x:
>>> 1 / 2
0
>>> 1.0 / 2.0
0.5
Python 3.x:
>>> 1/2
0.5
As for the // division method, this is called floor division, which automatically performs a floor operation on the result of the division. This behavior is consistent between Python 2.x and Python 3.x.
Python 2.x:
>>> -1 // 2
-1
Python 3.x:
>>> -1 // 2
-1
Note that this does not discard the decimal part, but rather performs a floor operation. To truncate the integer part, use the trunc function from the math module.
Python 3.x:
>>> import math
>>> math.trunc(1 / 2)
0
>>> math.trunc(-1 / 2)
0
Exceptions
Exception handling has also changed slightly in Python 3. 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.
Using the syntax except (exc1, exc2) as var allows you to catch multiple exception types simultaneously. Python 2.6 already supports both syntaxes.
- 1. In 2.x, all types of objects can be thrown directly. In 3.x, only objects that inherit from BaseException can be thrown.
- 2. In 2.x, the raise statement used a comma to separate the type of the thrown object and the argument. 3.x removes this unconventional syntax and now directly calls the constructor to throw the object.
In the 2.x era, exceptions not only signaled program errors but also often performed tasks normally performed by control structures. In 3.x, the designers made exceptions more specialized, requiring exception handling only in error-prone situations.
xrange
In Python 2, xrange() was a popular method for creating iterable objects, such as in for loops or list, set, or dictionary comprehensions.
This behaves very much like a generator (e.g., “lazy evaluation”). However, this xrange-iterable is infinite, meaning you can iterate over it indefinitely.
Due to its lazy evaluation, the xrange() function is faster than range() if you must iterate over it more than once (e.g., in a for loop). However, 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() so that there is no longer a dedicated xrange() function (xrange() throws a naming exception in Python 3).
import timeit
n=10000
def test_range(n):
return 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 'nntiming 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('timing 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(xrange(10))
NameError: name 'xrange' is not defined
Octal Literal Representation
Octal numbers must be written as 0o777; the old form 0777 is no longer acceptable; binary numbers 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 both syntaxes.
In Python 3.x, there is only one way to represent an octal literal: 0o1000.
Python 2.x
>>> 0o1000
512
>>> 01000
512
Python 3.x
>>> 01000
File "<stdin>", line 1
01000
^
SyntaxError: invalid token
>>> 0o1000
512
Not Equal Operator
In Python 2.x, there are two ways to write “not equal”: != and <>
In Python 3.x, the <> operator has been removed. There’s only one way to write it: !=. Fortunately, I’ve never had the habit of using <>.
Removed the repr expression “
In Python 2.x, the backtick ” is equivalent to the repr function
In Python 3.x, the ” expression has been removed, allowing only the repr function. Is this intended to make the code clearer? However, I find it rare to use repr, usually only for debugging. Most of the time, I still use the str function to describe objects with strings.
def sendMail(from_: str, to: str, title: str, body: str) -> bool:
pass
Several modules renamed (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 such as new, md5, and gopherlib have been removed. Python 2.6 already supports the new io module.
httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, and 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) Py3.X has removed the long type. Now there is only one integer type—int, but it behaves like the long type in 2.X.
2) The bytes type has been added, corresponding to the octet string type in 2.X. A bytes literal is defined as follows:
>>> b = b'china'
>>> type(b)
<type 'bytes'>
str objects and bytes objects can be encode()ed 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, while previous functions such as iterkeys() are deprecated. Also removed is
dict.has_key(); use in instead.