Python 2 的官方支持已于 2025 年 1 月 1 日结束,这意味着它不再收到任何安全更新或错误修复。强烈建议所有新项目都使用 Python 3,并将现有的 Python 2 代码迁移到 Python 3。
下面我将从几个核心方面详细解释它们的差别。
核心差异概览
| 特性/领域 | Python 2 | Python 3 | 说明 |
|---|---|---|---|
| 打印语句 | print "Hello" |
print("Hello") |
Python 3 将 print 变成了一个函数,更符合函数式编程思想,也支持 sep, end 等参数。 |
| 整数除法 | 3 / 2 结果是 1 |
3 / 2 结果是 5 |
Python 3 中, 总是执行浮点数除法,而 执行整数除法,Python 2 的 取决于操作数类型。 |
| Unicode 支持 | str 是字节串,unicode 是文本 |
str 是文本,bytes 是字节串 |
Python 3 将字符串处理得更清晰,从根源上解决了编码混乱的问题。 |
| 异常处理 | except Exception, e: |
except Exception as e: |
语法更现代化,与其他主流语言(如 Java, C++)保持一致。 |
xrange |
xrange(10) 生成一个 xrange 对象 |
不存在 | Python 3 中 range() 函数的行为与 Python 2 的 xrange() 相同,返回的是一个可迭代对象,节省内存。 |
next() 方法 |
my_iterator.next() |
next(my_iterator) |
迭代器的下一个值通过内置函数 next() 获取,而不是对象方法,更符合 Python 的函数式风格。 |
input() 函数 |
input() 会将输入作为代码执行 |
input() 总是返回字符串 |
Python 2 的 input() 很危险,Python 3 的 input() 相当于 Python 2 的 raw_input()。 |
| 关键字 | True, False, None 是内置常量 |
True, False, None 是关键字 |
Python 3 将它们提升为正式的关键字,有助于代码的严谨性。 |
| 库和模块 | urllib, urlparse 等 |
urllib 被拆分为 urllib.request, urllib.parse 等 |
Python 3 对标准库进行了重构和优化,模块结构更清晰。 |
详细解释
print 函数 vs print 语句
这是最直观、最容易发现的区别。
-
Python 2:
print是一个关键字,一种语句。print "Hello, World!" print "Hello", "World" # 输出: Hello World (默认用空格分隔) print "Hello", "World", # 输出: Hello World (末尾加逗号可以抑制换行)
-
Python 3:
print是一个内置函数,必须使用括号。print("Hello, World!") print("Hello", "World") # 输出: Hello World (默认用空格分隔) print("Hello", "World", end="!") # 输出: Hello World! (可以通过参数控制结束符) print("Hello", "World", sep=", ") # 输出: Hello, World (可以通过参数控制分隔符)优点: 将
print变成函数,使其行为更可预测和可配置,符合面向对象和函数式编程的原则。
整数除法
这是 Python 2 中最常见的“陷阱”之一。
-
Python 2: 当两个操作数都是整数时, 执行的是“地板除法”(Floor Division),结果会自动舍弃小数部分。
>>> 3 / 2 1 >>> 5 / 2 2
如果想得到浮点数结果,需要将其中一个数转为浮点数:
0 / 2或float(3) / 2。 -
Python 3: 总是执行“真除法”(True Division),结果是浮点数。
>>> 3 / 2 1.5 >>> 5 / 2 2.5
如果需要进行整数除法,需要使用 运算符。
>>> 5 // 2 2
优点:
3 / 2在数学上等于5,Python 3 的行为更符合直觉,避免了类型转换的麻烦。
Unicode 字符串
这是两者最核心、最根本的区别,也是 Python 3 最重要的改进之一。
-
Python 2:
str: 字节串,它只是原始的字节序列,不包含任何编码信息。"你好"在内存中存储的是编码后的字节。unicode: 文本字符串,它是一个抽象的 Unicode 字符序列,可以表示任何语言的字符。- 这导致了大量的编码混乱,开发者需要时刻记住
str和unicode的区别,并在读写文件、网络请求时进行繁琐的编码和解码。
-
Python 3:
str: 文本字符串,默认就是 Unicode 字符串,可以直接处理多语言字符。bytes: 字节串,当需要处理二进制数据(如文件读写、网络协议)时使用。- 这种设计从根源上理清了文本和二进制数据的区别。
# Python 3 # 字符串 my_string = "你好,世界" print(type(my_string)) # <class 'str'>
字节串
my_bytes = my_string.encode('utf-8') print(type(my_bytes)) # <class 'bytes'>
从字节串解码回字符串
my_string_decoded = my_bytes.decode('utf-8') print(my_string_decoded) # 你好,世界
**优点:** 大大简化了处理国际化文本和二进制数据的复杂度,减少了编码错误。
异常处理
语法上的小改动,但更清晰。
-
Python 2: 使用逗号来捕获异常变量。
try: # some code except ValueError, e: # 注意这里的逗号 print("An error occurred:", e) -
Python 3: 使用
as关键字,与其他语言(如 Java, C#)的语法一致。try: # some code except ValueError as e: # 注意这里的 as print("An error occurred:", e)优点: 语法更清晰、更现代化,
as的含义也更明确。
xrange 和 range
-
Python 2:
range(10): 会立即生成一个包含数字0到9的 列表,会占用较多内存。xrange(10): 返回一个xrange对象,它是一个 惰性计算的序列,只有在迭代时才会生成数字,非常节省内存。
-
Python 3:
range(): 合并了xrange的功能,它返回的是一个range对象,也是惰性计算的,行为和 Python 2 的xrange一样。xrange(): 这个函数不再存在。# Python 3 r = range(1000000) # 这不会立即创建一个包含100万个数字的列表 print(type(r)) # <class 'range'> print(r[999999]) # 只有在访问时才会计算
优点: 在 Python 3 中,
range()默认就是高效的模式,开发者无需在range和xrange之间做选择。
其他重要差异
-
input()的安全性:- Python 2:
input()会将用户输入的内容当作 Python 代码来执行,如果你输入"__import__('os').system('rm -rf /')",你的电脑可能会遭殃。raw_input()才是安全的,总是返回字符串。 - Python 3:
input()总是返回字符串,行为等同于 Python 2 的raw_input(),更加安全。
- Python 2:
-
标准库的重构:
urllib: Python 3 的urllib被拆分成了几个模块,如urllib.request(用于打开 URL),urllib.parse(用于解析 URL),urllib.error(处理异常),这使得库的功能更专注,结构更清晰。dict.keys(),dict.values(),dict.items():- Python 2: 这些方法返回的是列表。
- Python 3: 为了节省内存,它们返回的是“视图对象”(view objects),这是动态的、可迭代的视图,如果需要列表,可以显式地用
list()转换。
如何选择和迁移?
- 新项目: 毫不犹豫地选择 Python 3。
- 维护旧项目: 如果项目还在使用 Python 2,应尽快制定迁移计划,因为 Python 2 已不再安全。
- 如何迁移:
- 使用
2to3工具进行自动转换,它可以帮你处理大部分语法上的差异,但无法解决所有逻辑问题(比如除法行为)。 - 使用
six或future等兼容性库,让你的代码同时支持 Python 2 和 Python 3,这是一种过渡方案,但长远来看,最终目标是完全迁移到 Python 3。 - 手动重构: 最可靠的方法,在运行
2to3后,仔细审查代码,并进行人工测试,确保逻辑正确,特别是处理字符串和除法的地方。
- 使用
| 方面 | Python 2 (旧版) | Python 3 (现代) | 核心影响 |
|---|---|---|---|
| 设计哲学 | 兼容性优先 | 清晰、一致、现代 | Python 3 修正了历史遗留问题 |
| 易用性 | 陷阱多(如整数除法) | 直观、符合直觉 | 减少初学者困惑和常见错误 |
| 国际化 | 字符串处理复杂,易出错 | Unicode 作为核心,设计清晰 | 更好地支持全球化应用 |
| 性能 | - | 在很多方面有优化 | 效率更高,内存管理更优 |
| 生态系统 | 旧库停止更新 | 新库和框架都在积极开发 | Python 3 拥有更活跃的未来 |
Python 3 是一个更成熟、更强大、更易于使用的语言版本,虽然迁移过程可能需要一些工作,但从长远来看,它带来的好处远远超过了成本。
