Python 2与Python 3语法差异对比

了解两个版本之间的关键语法变化

简介

Python 3于2008年12月发布,带来了许多语法改进和新特性。本页面详细对比Python 2和Python 3之间的主要语法差异,帮助开发者理解并顺利迁移代码。

注意:Python 2已于2020年1月1日停止官方支持,建议所有项目迁移至Python 3。

2. 整数除法

Python 2

5 / 2    # 结果: 2 (整数除法)
5 / 2.0  # 结果: 2.5 (浮点除法)
5 // 2   # 结果: 2 (地板除法)

Python 3

5 / 2    # 结果: 2.5 (浮点除法)
5 // 2   # 结果: 2 (地板除法)
5 / 2.0  # 结果: 2.5 (浮点除法)

Python 3中,/运算符总是执行浮点除法,而不管操作数类型。如果需要整数除法,应使用//运算符。

这一变化使得除法行为更加直观和一致,符合数学直觉。

3. Unicode处理

Python 2

# 默认字符串是ASCII编码
s = "你好"  # 可能导致编码问题

# Unicode字符串需要前缀u
u = u"你好"  # Unicode字符串

# 字节字符串
b = "你好".encode('utf-8')

Python 3

# 默认字符串是Unicode编码
s = "你好"  # 正常Unicode字符串

# 字节字符串需要前缀b
b = b"hello"  # 只能包含ASCII字符

# 编码为字节
bytes_data = "你好".encode('utf-8')

Python 3中,所有字符串默认为Unicode字符串,这解决了Python 2中处理非ASCII文本的许多问题。

Python 3明确区分了文本字符串(str)和字节序列(bytes),使编码处理更加清晰。

4. 异常处理

Python 2

try:
    do_something()
except Exception, e:
    print e

# 多异常捕获
try:
    do_something()
except (TypeError, ValueError), e:
    print e

Python 3

try:
    do_something()
except Exception as e:
    print(e)

# 多异常捕获
try:
    do_something()
except (TypeError, ValueError) as e:
    print(e)

Python 3使用as关键字捕获异常,语法更加清晰。

这种语法更符合Python的整体设计理念,避免了逗号可能带来的歧义。

5. range与xrange

Python 2

# 创建列表
r = range(10)  # [0, 1, 2, ..., 9]

# 创建迭代器,更节省内存
x = xrange(10)  # xrange对象

for i in xrange(1000000):  # 内存高效
    pass

Python 3

# 创建迭代器,行为类似Python 2的xrange
r = range(10)  # range对象,不是列表

# xrange不再存在
# 转换为列表需要显式操作
l = list(range(10))  # [0, 1, 2, ..., 9]

for i in range(1000000):  # 内存高效
    pass

Python 3中的range函数返回迭代器而非列表,行为类似Python 2中的xrange,更加内存高效。

xrange函数在Python 3中被移除,因为range已经提供了相同的功能。

6. 迭代器方法

Python 2

it = iter([1, 2, 3])
it.next()  # 返回1
it.next()  # 返回2

# 实现迭代器
class MyIterator:
    def __iter__(self):
        return self
    def next(self):
        # 实现逻辑

Python 3

it = iter([1, 2, 3])
next(it)  # 返回1
next(it)  # 返回2
it.__next__()  # 返回3

# 实现迭代器
class MyIterator:
    def __iter__(self):
        return self
    def __next__(self):
        # 实现逻辑

Python 3中,迭代器的next()方法改名为__next__(),与其他特殊方法的命名更加一致。

推荐使用内置函数next(iterator)而不是调用迭代器的方法。

7. 输入函数

Python 2

# 获取原始输入字符串
name = raw_input("请输入姓名: ")

# 获取并计算输入的Python表达式
result = input("请输入表达式: ")
# 输入 1+2 会返回 3
# 有安全风险

Python 3

# 获取输入字符串
name = input("请输入姓名: ")

# 要计算表达式,需要显式使用eval
expr = input("请输入表达式: ")
result = eval(expr)  # 谨慎使用eval

Python 3中,raw_input()被移除,input()的行为变为获取字符串输入(类似Python 2的raw_input())。

这一变化提高了安全性,避免了Python 2中input()可能导致的代码注入风险。

8. 类语法

Python 2

# 经典类
class OldClass:
    def method(self):
        pass

# 新式类
class NewClass(object):
    def method(self):
        pass

Python 3

# 所有类都是新式类
class MyClass:
    def method(self):
        pass

# 显式继承object是可选的
class MyClass2(object):
    def method(self):
        pass

Python 3中,所有类默认都是新式类,不再需要显式继承object

新式类提供了更一致的方法解析顺序、更好的属性查找机制和对描述符的支持。

9. 不等运算符

Python 2

# 两种不等运算符
if a != b:
    print "不相等"

if a <> b:  # 另一种不等运算符
    print "不相等"

Python 3

# 只有一种不等运算符
if a != b:
    print("不相等")

# <> 运算符已被移除

Python 3移除了<>不等运算符,只保留!=,使语法更加一致。

这减少了语法的冗余性,符合Python"用一种方法做一件事"的设计理念。

10. 字典方法

Python 2

d = {'a': 1, 'b': 2}

# 返回列表
keys = d.keys()     # ['a', 'b']
values = d.values() # [1, 2]
items = d.items()   # [('a', 1), ('b', 2)]

# 迭代
for k in d.iterkeys():
    print k

Python 3

d = {'a': 1, 'b': 2}

# 返回视图对象,而非列表
keys = d.keys()     # dict_keys(['a', 'b'])
values = d.values() # dict_values([1, 2])
items = d.items()   # dict_items([('a', 1), ('b', 2)])

# 转换为列表
keys_list = list(d.keys())

# iterkeys()等方法已移除
for k in d.keys():  # 或直接 for k in d:
    print(k)

Python 3中,字典方法.keys().values().items()返回视图对象而非列表,这些视图对象会动态反映字典的变化。

Python 2中的.iterkeys().itervalues().iteritems()方法在Python 3中被移除,因为常规方法已经返回迭代器。