Differences between Python 2.x and 3.x

Python 3.0, often referred to as Python 3000, or simply Py3k, is a major upgrade relative to earlier versions of Python.

In order not to bring in too much baggage, Python 3.0 was designed without considering backward compatibility.

Many programs designed for earlier versions of Python cannot run properly on Python 3.0.

To accommodate existing programs, Python 2.6 serves as a transitional version, basically using 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.

For new Python programs, it is 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. Currently, third-party libraries that do not support Python 3.0 include Twisted, py2exe, PIL, etc.

Most third-party libraries are striving to be 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 with Python 2.6 or Python 2.7.

The changes in Python 3.0 are mainly in the following aspects:


print function

The print statement is gone, replaced by theprint()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"
print ("fish") # 注意print后面有个空格
print("fish") # print()不能带有任何其它参数

However, Python 2.6 already supports the new print() syntax, for example:

from __future__ import print_function
print("fish", "panda", sep=', ')

If you want to use the Python 3.x print function in Python 2.x, you can import the__future__package, which disables the Python 2.x print statement and adopts the Python 3.x print function:

Example

>>> list =["a", "b", "c"]
>>> print list    # python2.x print statement
['a', 'b', 'c']
>>> from __future__ import print_function  # Import the __future__ package
>>> print list     # Python2.x print statement is disabled, using it causes an error
  File "<stdin>", line 1
    print list
             ^
SyntaxError: invalid syntax
>>> print (list)   # Use Python3.x print function
['a', 'b', 'c']
>>>

Many compatibility features between Python3.x and Python2.x can be imported through__future__this package.


Unicode

Python 2 has an ASCII str() type, and unicode() is separate, not a byte type.

Now, in Python 3, we finally have Unicode (utf-8) strings, and a byte class: bytes and bytearrays.

Since Python3.x source files use utf-8 encoding by default, using Chinese 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

Division in Python seems very sophisticated compared to other languages, with a complex set of rules. There are two operators for division in Python:/and//

First, let's talk about/division:

In Python 2.x,/division is like in most languages we are familiar with, such as Java and C: integer division results in an integer, completely ignoring the fractional part, while float division retains the decimal part and yields a float result.

In Python 3.x,/division no longer does this; the result of dividing integers is also a float.

Python 2.x:

>>> 1 / 2
0
>>> 1.0 / 2.0
0.5

Python 3.x:

>>> 1/2
0.5

As for//division, this kind of division is called floor division. It automatically performs a floor operation on the result of the division, and it is consistent in Python 2.x and Python 3.x.

python 2.x:

>>> -1 // 2
-1

python 3.x:

>>> -1 // 2
-1

Note that it does not discard the fractional part, but performs a floor operation. If you want to truncate the integer part, you need to 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 changed fromexcept exc, vartoexcept exc as var。

Using the syntax 'except (exc1, exc2) as var' can catch multiple types of exceptions at the same time. Python 2.6 already supports both syntaxes.

  • 1. In the 2.x era, all types of objects could be thrown directly. In the 3.x era, only objects derived from BaseException can be thrown.
  • 2. In 2.x, the raise statement used a comma to separate the thrown object type and the argument. 3.x removed this weird syntax; you can simply call the constructor to raise an object.

In the 2.x era, besides indicating program errors, exceptions were often used for things that ordinary control structures should do. In 3.x, you can see that the designers made exceptions more specific; exception handling statements should only be used when errors occur.

Python 2.xThe exception handling syntax uses a comma.

try:
    # code
except Exception, e:
    print e

Python 3.xThe exception handling syntax uses 'as'.

try:
    # code
except Exception as e:
    print(e)

xrange() and range()

Python 2.xrange() returns a list, while xrange() returns a generator (more memory-efficient).

range(5)  # 返回 [0, 1, 2, 3, 4]
xrange(5)  # 返回 xrange 对象,按需生成数字

Python 3.xxrange() was removed, and range() returns a generator, saving memory.

range(5)  # 返回一个迭代器,按需生成数字

Octal literal representation

Octal numbers must be written as 0o777; the old form 0777 can no longer be used; binary must be written as0b111。

Added abin()function to convert an integer into a binary string. Python 2.6 already supports both syntaxes.

In Python 3.x, there is only one way to represent an octal literal, 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 operators

In Python 2.x, there are two ways to write 'not equal': != and <>

In Python 3.x, <> was removed, leaving only !=. Luckily, I never got into the habit of using <>.


Removed the repr expression ``

In Python 2.x, backticks `` are equivalent to the repr function.

Python 3.x removed the `` syntax and only allows the repr function. Is this to make the code look clearer? However, I feel that the opportunity to use repr is rare; I generally use it only when debugging. Most of the time, I use the str function to describe objects as strings.

def sendMail(from_: str, to: str, title: str, body: str) -> bool:
    pass

Multiple modules were renamed (according to PEP8)

Old names New names
_winreg winreg
ConfigParser configparser
copy_reg copyreg
Queue queue
SocketServer socketserver
repr reprlib

The StringIO module is now merged into the new io module. Modules such as new, md5, gopherlib were removed. Python 2.6 already supports the new io module.

httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, and cookielib were merged into the http package.

The exec statement was removed, leaving only the exec() function. Python 2.6 already supports the exec() function.


5. Data types

1) Py3.X removed the long type. Now there is only one integer type — int, but its behavior is like the long type in 2.X.

2) A new bytes type was added, corresponding to the 8-bit string in 2.X. To define a bytes literal:

>>> b = b'china' 
>>> type(b) 
<type 'bytes'> 

str and bytes objects can use .encode() (str -> bytes) or .decode() (bytes -> str) methods to convert to each other.

>>> s = b.decode() 
>>> s 
'china' 
>>> b1 = s.encode() 
>>> b1 
b'china' 

3) The dict methods .keys(), .items(), and .values() return iterators, while the previous functions such as iterkeys() are deprecated. Also removed is dict.has_key(); use 'in' instead.


6. Standard library reorganization

Python 3.x: Some modules were reorganized or renamed. For example, urllib and urlparse were merged into urllib.

# Python 2.x
import urllib
import urlparse

# Python 3.x
import urllib.parse

7. Function's iteritems() and items()

Python 2.x: Dictionaries have items() and iteritems() methods; items() returns a list, iteritems() returns an iterator.

d = {'a': 1, 'b': 2}
d.items()     # 返回 [('a', 1), ('b', 2)]
d.iteritems()  # 返回字典的迭代器

Python 3.x: iteritems() was removed, and items() returns a dictionary view (i.e., an iterator).

d = {'a': 1, 'b': 2}
d.items()     # 返回 dict_items([('a', 1), ('b', 2)])

8. Module support for __future__

Python 3.x: Many Python 2.x features have been removed. Python 2.x users who want to use Python 3.x behavior in advance in their code can use __future__ imports to achieve compatibility.

from __future__ import print_function

9. Dictionary sorting

Python 2.x: Dictionaries are unordered (no guaranteed order).

Python 3.x: Dictionaries are ordered, preserving elements in insertion order.

10. next() method

Python 2.x: next() is a function, usually used with iter().

Python 3.x: next() is a built-in function, used in the same way as in Python 2.x, but its parameters are different. In Python 3.x, a default value can be set via next(iterator, default).

Other extensions