Skip to content

Python 3 新特性

Python 3 的主要特性及与 Python 2 的区别

Section titled “Python 3 的主要特性及与 Python 2 的区别”

与 Python 2(已于 2020 年终止支持,即 end-of-life)相比,Python 3 引入了多项重大变化和改进。理解这些区别有助于阐明 Python 3 中某些功能的工作原理,并提供了历史背景。

这是最显著的变化之一。在 Python 3 中,print 是一个内置函数(built-in function),需要在其参数(arguments)周围加上括号 ()。在 Python 2 中,print 是一个语句(statement),括号是可选的。

# Python 3(正确)
print("Hello, World!")
# Python 2 风格(在 Python 3 中会产生 SyntaxError)
# print "Hello, World"

print() 函数还包含可选的关键字参数(keyword arguments),如 sep(参数之间的分隔符,separator)和 end(附加在末尾的字符,默认为换行符 \n)。

# Python 3: 控制分隔符和结束字符
print("apple", "banana", "cherry", sep=", ")
print("This line stays on the same", end=" ")
print("line.")
# 输出:
# apple, banana, cherry
# This line stays on the same line.

在 Python 2 中,抑制换行通常需要在末尾加上逗号,但在 Python 3 中这已不是用于此目的的有效语法(syntax)。

在 Python 3 中,除法运算符 / 总是执行浮点除法(floating-point division),即使是整数之间也是如此。这通常更直观。

# Python 3
result = 3 / 2
print(result) # 输出: 1.5

如果需要整除(integer division,舍弃余数),请使用向下取整除法运算符(floor division operator)//。

# Python 3: 向下取整除法
result_floor = 3 // 2
print(result_floor) # 输出: 1
result_neg = -3 // 2
print(result_neg) # 输出: -2(向负无穷方向取整)

在 Python 2 中,如果两个操作数(operands)都是整数,/ 执行整除(例如 3 / 2 结果是 1);只有当至少一个操作数是浮点数(float)时,才执行浮点除法(例如 3.0 / 2 结果是 1.5)。这一区别是常见的错误(bug)来源。

Python 3 默认使用 Unicode(在大多数环境中特指 UTF-8)处理所有字符串(string,str 类型)。这直接提供了对国际字符和 emoji 的更好支持。

# Python 3
my_string = "你好世界 €"
print(my_string)
print(type(my_string)) # 输出: <class 'str'>

为了表示原始字节序列(raw bytes),Python 3 使用 bytes 类型。可以使用 b 前缀创建字节字面值(bytes literals)。

# Python 3
my_bytes = b"\x48\x65\x6c\x6c\x6f" # 表示 ASCII "Hello"
print(my_bytes)
print(type(my_bytes)) # 输出: <class 'bytes'>
# 将字符串编码为字节
encoded_string = my_string.encode('utf-8')
print(encoded_string)
print(type(encoded_string)) # 输出: <class 'bytes'>
# 将字节解码为字符串
decoded_string = encoded_string.decode('utf-8')
print(decoded_string) # 输出: 你好世界 €

在 Python 2 中,默认的 str 类型处理 ASCII 字符,需要一个单独的 unicode 类型(通常使用 u 前缀创建,例如 u"你好")来处理 Unicode 文本。在 Python 2 中,区分字节(bytes)和文本(text)的处理更加复杂且容易出错。

在 Python 3 中,range() 函数返回一个不可变序列类型(immutable sequence type)(一个 ‘range object’),它在你迭代(iterate)时按需生成数字。这对于大范围的数字来说是内存高效(memory-efficient)的。

# Python 3
my_range = range(1, 10, 2) # 表示 1, 3, 5, 7, 9
print(my_range) # 输出: range(1, 10, 2)
print(type(my_range)) # 输出: <class 'range'>
for i in my_range:
print(i, end=" ") # 输出: 1 3 5 7 9
# Range 对象支持切片(slicing)(Python 3.2+)
print("\n", my_range[1:3]) # 输出: range(3, 7, 2)

在 Python 2 中,range() 会在内存中创建一个完整的数字列表(list),这可能效率低下。Python 2 有一个单独的 xrange() 函数,其行为类似于 Python 3 的 range()(延迟生成数字)。在 Python 3 中,xrange() 被移除,range() 采用了其高效的行为。

异常处理(Exception Handling)语法

Section titled “异常处理(Exception Handling)语法”

在 Python 3 中,需要在 except 代码块(block)中使用 as 关键字将捕获到的异常对象(exception object)赋值给一个变量。

# Python 3(正确)
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"Caught an exception: {e}")
print(f"Exception type: {type(e)}")
# Python 2 风格(在 Python 3 中会产生 SyntaxError)
# except ZeroDivisionError, e:

此外,引发异常(raising exceptions)时需要将异常参数(exception arguments)括在括号内。

# Python 3(正确)
raise ValueError("Invalid input provided")
# Python 2 风格(在 Python 3 中会产生 SyntaxError)
# raise ValueError, "Invalid input provided"

在 Python 3 中,input() 函数总是将用户输入读取为字符串(string)。如果需要将输入视为数字,必须显式地进行类型转换(convert)。

# Python 3
user_name = input("Enter your name: ")
print(f"Hello, {user_name}! Type: {type(user_name)}")
user_age_str = input("Enter your age: ")
try:
user_age_int = int(user_age_str)
print(f"Your age is {user_age_int}. Type: {type(user_age_int)}")
except ValueError:
print("Invalid age entered.")

在 Python 2 中,有两个函数:raw_input()(其行为类似于 Python 3 的 input(),总是返回一个字符串)和 input()(它会尝试将输入作为 Python 代码进行求值,存在安全风险且经常引起混淆)。Python 3 移除了 raw_input() 并使 input() 的行为更安全。

要从迭代器(例如由 iter() 或生成器函数(generator functions)创建的迭代器)获取下一个项目,在 Python 3 中需要使用内置函数 next()。

# Python 3
my_list = [10, 20, 30]
my_iterator = iter(my_list)
item1 = next(my_iterator)
print(item1) # 输出: 10
item2 = next(my_iterator)
print(item2) # 输出: 20
# 直接调用 .next() 方法会引发错误
# item3 = my_iterator.next() # 在 Python 3 中产生 AttributeError

在 Python 2 中,迭代器有一个 .next() 方法可以直接调用。Python 3 标准化为使用 next() 函数。

  • 字典视图(Dictionary Views): 在 Python 3 中,.keys()、.values() 和 .items() 等方法返回内存高效的 ‘视图’ 对象(view objects),而不是像 Python 2 中那样返回列表(lists)。如果需要,可以将它们转换为列表:list(my_dict.keys())。
  • 元类语法(Metaclass Syntax): 指定元类(metaclasses)的方式发生了变化。
  • 标准库重组(Standard Library Reorganization): 一些模块(modules)被重命名或移动了(例如,urllib2 现在是 urllib 的一部分)。
  • 函数注解(Function Annotations): Python 3 引入了用于类型提示(type hints)的语法(参见 typing 模块)。

__future__ 模块在 Python 2 中用于选择性地启用来自 Python 3 的特性,以方便过渡。例如,from __future__ import division 会使 / 在 Python 2 中执行浮点除法。

虽然对于迁移具有历史意义,但这些导入(imports)在 Python 3 中没有效果,并且在现代 Python 3 代码中通常不再需要。

Python 包含一个名为 2to3 的命令行工具(command-line tool),它可以自动将大多数 Python 2 代码转换为 Python 3 语法。它应用了一系列修复器(fixers)来处理诸如 print 语句变为函数、模块重命名以及异常语法更新等变化。

虽然在主要的迁移时期很有用,但由于目前大多数活跃的开发直接在 Python 3 中进行,它的相关性已不如从前。然而,了解它的存在为多年前遇到的过渡挑战提供了背景信息。

# Python 2 代码片段示例:
def greet(name):
print "Hello,", name
# 在此代码片段上运行 '2to3' 会建议将其更改为:
def greet(name):
print("Hello,", name)