Python 3 是现在和未来的标准,而 Python 2 已在 2025 年 1 月 1 日官方停止支持,对于任何新项目,都应该毫不犹豫地选择 Python 3。

下面我将从几个核心方面详细阐述它们之间的区别。
核心语法差异
a) print 语句
这是最著名、最直观的区别之一。
-
Python 2:
print是一个语句,不是函数。# 输出字符串 print "Hello, World!" # 输出多个值,用空格分隔 print "Hello", "World" # 如果想抑制末尾的换行符,需要在末尾加逗号 print "Hello,", print "World"
-
Python 3:
print是一个函数,必须使用括号。
(图片来源网络,侵删)# 输出字符串 print("Hello, World!") # 输出多个值,用空格分隔 print("Hello", "World") # 抑制末尾的换行符,使用 end 参数 print("Hello", end=" ") print("World")
b) 整数除法
这是另一个非常重要的变化,直接影响数学计算。
-
Python 2: 当两个整数相除时,结果会自动截断为整数(向下取整)。
>>> 5 / 2 2 >>> -5 / 2 -3 # 注意,是向下取整
-
Python 3: 执行真除法,结果总是浮点数,而 执行整数除法(向下取整)。
>>> 5 / 2 2.5 >>> -5 / 2 -2.5 # 使用 // 进行整数除法 >>> 5 // 2 2 >>> -5 // 2 -3
c) Unicode 支持
这是两者在处理文本上的根本性区别。

-
Python 2: 有两种字符串类型:
str: 字节串,是机器的底层表示。unicode: Unicode 字符串,是抽象的文本表示。 默认情况下,"你好"是一个str(字节串),如果包含非 ASCII 字符,很容易引发编码错误。
-
Python 3: 有两种字符串类型:
str: Unicode 字符串,是文本的默认表示。bytes: 字节串,用于处理二进制数据。 默认情况下,"你好"就是一个str(Unicode 字符串),处理多语言文本更加自然和简单。
d) xrange vs range
-
Python 2:
range(): 会立即生成一个包含所有数字的列表,当范围很大时,会占用大量内存。xrange(): 返回一个 xrange 对象,它是一个序列对象,在迭代时才生成数字,内存效率极高。
-
Python 3:
range()的行为被修改为等同于 Python 2 的xrange(),它返回的是一个range对象(一个不可变的序列),内存效率高。xrange()这个名称被移除了。
# Python 3 r = range(1000000) # 这不会立即创建一个包含100万个数字的列表 for i in r: # 在迭代时,数字才被按需生成 pass
e) 异常处理语法
-
Python 2: 捕获异常和获取异常值的方式。
try: # 尝试执行的代码 1 / 0 except ZeroDivisionError, e: # 注意这里的逗号 print("Error: %s" % e) -
Python 3: 使用了更现代、更清晰的
as关键字。try: # 尝试执行的代码 1 / 0 except ZeroDivisionError as e: # 使用 as 关键字 print("Error: %s" % e)
f) 迭代器 .next() 方法
-
Python 2: 迭代器的下一个元素是通过
.next()方法获取的。my_list = [1, 2, 3] it = iter(my_list) print(it.next()) # 输出 1
-
Python 3:
.next()方法被内置函数next()替代,这样所有可迭代对象都可以使用统一的方式。my_list = [1, 2, 3] it = iter(my_list) print(next(it)) # 输出 1
库和模块差异
-
urllib重构:- Python 2:
urllib,urllib2,urlparse等模块功能分散,使用起来比较混乱。 - Python 3: 将这些模块重构并统一为
urllib.request,urllib.parse,urllib.error等,结构更清晰。
- Python 2:
-
configparser:- Python 2: 模块名为
ConfigParser(大小写混合)。 - Python 3: 模块名统一为小写
configparser。
- Python 2: 模块名为
-
queue:- Python 2: 队列模块名为
Queue(大写 Q)。 - Python 3: 模块名统一为小写
queue。
- Python 2: 队列模块名为
其他重要区别
| 特性 | Python 2 | Python 3 |
|---|---|---|
| 默认编码 | 源码文件默认是 ASCII | 源码文件默认是 UTF-8 |
| 关键字 | exec 是一个语句 |
exec 是一个函数,exec(...) |
input() vs raw_input() |
input() 会将输入作为表达式执行(不安全),raw_input() 总是返回字符串 |
input() 总是返回字符串,raw_input() 被移除 |
| 列表推导式作用域 | 列表推导式会泄露循环变量到外部作用域 | 列表推导式有自己独立的作用域,不会泄露变量 |
| 八进制字面量 | 0755 (前导零) |
0o755 (前导 0o) |
如何从 Python 2 迁移到 Python 3?
由于代码不兼容,手动修改代码是繁琐且容易出错的,社区提供了强大的自动化工具来辅助迁移。
最著名的工具是 2to3,它是一个 Python 程序,可以读取你的 Python 2 代码,自动将其转换为 Python 3 代码。
使用步骤:
- 安装
lib2to3工具(Python 自带)。 - 在命令行运行:
# 将 my_script.py 转换为 my_script.py.bak(备份)并生成新的 my_script.py 2to3 -w my_script.py
- 重要:
2to3不能解决所有问题(特别是依赖于特定库行为的代码),转换后仍然需要人工测试和修复。
对于大型项目,可以使用 modernize 或 futurize 等更智能的工具,它们可以提供“向前兼容”的代码,让你的代码同时在 Python 2 和 Python 3 环境下运行(作为过渡方案)。
| 方面 | Python 2 (旧版) | Python 3 (新版) |
|---|---|---|
| 状态 | 已停止支持 | 当前和未来标准 |
print |
语句 print "..." |
函数 print("...") |
| 除法 | 是整数除法 | 是真除法, 是整数除法 |
| 字符串 | str (字节) 和 unicode (文本) |
str (Unicode 文本) 和 bytes (字节) |
| 迭代器 | .next() 方法 |
next() 内置函数 |
| 异常捕获 | except Exception, e: |
except Exception as e: |
xrange |
存在,内存高效 | 已移除,range() 具备其功能 |
| 库 | 模块名和结构较混乱 | 重构和统一,更清晰 |
除非你需要维护一个非常古老的、无法迁移的 Python 2 项目,否则永远应该选择 Python 3,它修复了 Python 2 的许多设计缺陷,提供了更清晰、更一致、更强大的语言特性,并且拥有更活跃的社区和更丰富的现代库支持。
