Skip to content

Python 历史与版本演进 ​

Python 从 1989 年圣诞节的一次「业余项目」起步,历经三十多年演进,成为当今最主流的编程语言之一。理解版本演进的历史,不仅能帮你读懂老代码,更能让你理解每一个现代特性背后的设计动机。本节将梳理关键时间线、版本特性与生命周期策略。

前置知识

阅读本节前,建议先了解:Python 是什么,理解 Python 的基本定位与「Python 之禅」。

基础概念 ​

Python 的版本号遵循 主版本.次版本.修订号(如 3.12.5)的语义化格式。主版本变更(2 → 3)意味着不向后兼容的重大改动;次版本(3.11 → 3.12)每年发布一次,带来新语法与性能改进;修订号(3.12.4 → 3.12.5)只包含 Bug 修复与安全补丁。

概念英文说明
主版本Major Version破坏性变更,如 Python 2 到 3
次版本Minor Version年度功能发布,如 3.12
修订号Micro / PatchBug 与安全修复
预发布版Pre-releasealpha、beta、rc 等测试版本
生命周期Lifecycle从功能冻结到停止支持的全过程
增强提案PEPPython Enhancement Proposal,特性设计的正式文档

语法与用法 ​

在写任何代码之前,先确认运行环境的版本,是养成良好习惯的第一步:

python
# 查看当前 Python 版本信息
import sys

# version_info 是具名元组,可直接比较
print(sys.version_info)
print(f"主版本:{sys.version_info.major}")
print(f"次版本:{sys.version_info.minor}")
print(f"修订号:{sys.version_info.micro}")
print(f"发行级别:{sys.version_info.releaselevel}")
print(sys.version)  # 含编译信息的完整字符串
text
sys.version_info(major=3, minor=12, micro=5, releaselevel='final', serial=0)
主版本:3
次版本:12
修订号:5
发行级别:final
3.12.5 (main, Aug  6 2024, 19:08:49) [Clang 15.0.0]

详细说明 ​

版本时间线 ​

下表列出了 Python 3 各主要版本的关键特性,是理解现代 Python 的必备参照:

版本发布时间关键特性状态
Python 1.01994-01函数式工具 lambda、map、filter已停止
Python 2.02000-10列表推导、垃圾回收改进、Unicode2020-01 停止支持
Python 3.02008-12print 变函数、默认 Unicode、统一整除已停止
Python 3.62016-12f-string、变量注解、字典有序已停止
Python 3.72018-06dataclasses、async/await 稳定、__future__ 延迟注解2023-06 停止支持
Python 3.82019-10海象运算符 :=、仅位置参数 /、f-string =2024-10 停止支持
Python 3.92020-10内置泛型 list[int]、字典合并 `、str.removeprefix`
Python 3.102021-10结构化模式匹配 match、联合类型 X | Y、更清晰的错误安全支持中
Python 3.112022-10异常组 except*、Self 类型、大幅性能提升(快约 25%)安全支持中
Python 3.122023-10类型参数语法 type X = ...、f-string 增强、Perf 优化全面支持中
Python 3.132024-10实验性 free-threaded(无 GIL)、改进的 REPL、JIT 实验特性全面支持中
Python 3.142025-10延迟注解求值、模板字符串 t-string、多解释器增强全面支持中

版本节奏

自 Python 3.x 的 3.6 起,CPython 形成了「每年 10 月发布一个次版本」的固定节奏。每个次版本获得约 5 年支持:前 2 年全面支持(含新特性),后 3 年仅提供安全修复。

Python 2 与 Python 3 的分裂 ​

Python 3.0 为了修复历史遗留设计缺陷,进行了不向后兼容的重构,这成为编程语言史上最著名的迁移案例之一:

变化点Python 2Python 3
输出print "hello"print("hello")
字符串str 为字节,unicode 为文本str 为文本,bytes 为字节
整除3 / 2 == 1(整数除法)3 / 2 == 1.5(真除法)
迭代器dict.keys() 返回列表返回视图对象
输入raw_input()input()
异常语法except E, e:except E as e:
python
# Python 3 中以上差异的正确写法
text: str = "中文文本"          # str 表示 Unicode 文本
data: bytes = text.encode("utf-8")  # bytes 表示字节序列

print(text)
print(data)
print(text.encode("utf-8").decode("utf-8"))
print(f"整数真除法:3 / 2 = {3 / 2}")     # 1.5
print(f"整数地板除:3 // 2 = {3 // 2}")   # 1
text
中文文本
b'\xe4\xb8\xad\xe6\x96\x87\xe6\x96\x87\xe6\x9c\xac'
中文文本
整数真除法:3 / 2 = 1.5
整数地板除:3 // 2 = 1

Python 2 已于 2020 年 1 月 1 日正式停止支持,所有新项目都应使用 Python 3。

近代版本的重要特性 ​

Python 3.8:海象运算符 ​

:= 允许在表达式内部赋值,避免了「计算一次、再用一次」的重复调用:

python
# Python 3.8+
# 不推荐:调用两次 len(),或先单独赋值
data = [1, 2, 3, 4, 5]
if len(data) > 3:
    print(f"列表长度 {len(data)} 超过限制")

# 推荐:海象运算符一次赋值并在条件中使用
if (n := len(data)) > 3:
    print(f"列表长度 {n} 超过限制")
text
列表长度 5 超过限制
列表长度 5 超过限制

Python 3.9:内置泛型与字典合并 ​

python
# Python 3.9+:内置类型可直接作为泛型,无需 typing.List
def merge_scores(a: dict[str, int], b: dict[str, int]) -> dict[str, int]:
    """合并两份成绩单,后者覆盖前者"""
    return a | b

print(merge_scores({"alice": 90}, {"bob": 85, "alice": 95}))

# 字符串新方法
filename = "report.tar.gz"
print(filename.removeprefix("report."))  # 去掉前缀
print(filename.removesuffix(".gz"))      # 去掉后缀
text
{'alice': 95, 'bob': 85}
tar.gz
report.tar

Python 3.10:结构化模式匹配 ​

match 语句提供了比 if/elif 更清晰的多分支结构匹配:

python
# Python 3.10+
def handle_command(command: dict[str, object]) -> str:
    """根据命令字典分发处理逻辑"""
    match command:
        case {"action": "create", "name": str(name)}:
            return f"创建资源:{name}"
        case {"action": "delete", "name": str(name)}:
            return f"删除资源:{name}"
        case {"action": "list", "limit": int(limit)}:
            return f"列出最多 {limit} 项"
        case {"action": "list"}:
            return "列出全部(默认限制)"
        case _:
            return "未知命令"

print(handle_command({"action": "create", "name": "user"}))
print(handle_command({"action": "list", "limit": 10}))
print(handle_command({"action": "list"}))
print(handle_command({"action": "unknown"}))
text
创建资源:user
列出最多 10 项
列出全部(默认限制)
未知命令

Python 3.11:异常组与性能提升 ​

python
# Python 3.11+:异常组可一次抛出多个独立异常
def validate_user(user: dict[str, object]) -> None:
    """校验用户数据,收集所有错误后一次性抛出"""
    errors: list[ValueError] = []
    if not user.get("name"):
        errors.append(ValueError("name 不能为空"))
    if user.get("age", 0) < 18:
        errors.append(ValueError("age 必须大于等于 18"))
    if errors:
        raise ExceptionGroup("用户数据校验失败", errors)

try:
    validate_user({"name": "", "age": 15})
except* ValueError as group:
    # except* 可捕获异常组中匹配类型的子集
    for exc in group.exceptions:
        print(f"发现错误:{exc}")
text
发现错误:name 不能为空
发现错误:age 必须大于等于 18

Python 3.12:类型参数语法 ​

PEP 695 让泛型写法更简洁自然:

python
# Python 3.12+
type Priority = int                      # 类型别名
type Callback[T] = list[str] | None      # 泛型类型别名

class Stack[T]:
    """一个通用的后进先出栈"""

    def __init__(self) -> None:
        self._items: list[T] = []

    def push(self, item: T) -> None:
        self._items.append(item)

    def pop(self) -> T:
        return self._items.pop()

    def __len__(self) -> int:
        return len(self._items)

stack: Stack[str] = Stack()
stack.push("a")
stack.push("b")
print(len(stack), stack.pop(), stack.pop())
text
2 b a

Python 3.13:自由线程与改进 REPL ​

python
# Python 3.13+:新的交互式 REPL 支持多行编辑与彩色回溯(仅终端体验)
# 检查是否运行在 free-threaded(无 GIL)构建上
import sys

# 该属性仅在支持 free-threading 的构建中存在
free_threaded = getattr(sys, "_is_gil_enabled", lambda: None)()
print(f"GIL 是否启用:{free_threaded}")
text
GIL 是否启用:True

free-threaded 仍在实验阶段

Python 3.13 的 free-threaded(无 GIL)构建需要在安装时专门选择,且部分 C 扩展尚不兼容。生产环境建议继续使用标准构建,等待生态完善。

版本生命周期与支持策略 ​

CPython 采用「滚动支持窗口」:每个次版本约 5 年,其中前 2 年为全面支持(Bug 修复),后 3 年为安全支持(仅安全补丁):

阶段时长内容
特性开发约 1 年新特性合并,进入 alpha/beta
Bug 修复(Bugfix)约 2 年修复 Bug,接受安全补丁
安全修复(Security)约 3 年只修复安全漏洞
生命周期终止(EOL)—不再发布任何更新
python
# 一个实用的版本守卫:在程序入口检查版本是否满足要求
import sys
from dataclasses import dataclass

@dataclass(frozen=True)
class VersionRequirement:
    """版本要求描述"""
    minimum: tuple[int, int]
    reason: str

    def check(self) -> bool:
        """检查当前解释器是否满足要求"""
        return sys.version_info[:2] >= self.minimum

def require(req: VersionRequirement) -> None:
    """不满足版本要求时直接退出并给出清晰提示"""
    if not req.check():
        current = ".".join(map(str, sys.version_info[:3]))
        required = ".".join(map(str, req.minimum))
        raise SystemExit(
            f"需要 Python {required}+({req.reason}),当前版本 {current}"
        )

require(VersionRequirement((3, 11), "使用了 ExceptionGroup 与会话优化"))
print("版本检查通过")
text
版本检查通过

实战示例 ​

示例一:编写兼容多版本的代码 ​

现实中要在一段时间内支持多个 Python 版本,可用 sys.version_info 分支或特性探测:

python
import sys

# 方案一:按版本号分支
if sys.version_info >= (3, 12):
    type NumberList = list[int]      # 3.12+ 的 type 语句
    print("使用 3.12+ 的类型参数语法")
else:
    from typing import List
    NumberList = List[int]           # 旧版本回退写法
    print("使用兼容写法")

# 方案二:特性探测(推荐,更健壮)
import shutil

# shutil.rmtree 的 onexc 参数是 3.12 新增的
supports_onexc = "onexc" in shutil.rmtree.__doc__ if shutil.rmtree.__doc__ else False
print(f"支持 onexc 参数:{supports_onexc}")
text
使用 3.12+ 的类型参数语法
支持 onexc 参数:True

示例二:用特性开关渐进式采用新语法 ​

大型项目常用「渐进升级」策略:先升级解释器,再逐步采用新特性:

python
# 一份通用的「版本能力检测表」,便于项目内部查询
import sys
import typing

CAPABILITIES: dict[str, tuple[int, int]] = {
    "walrus": (3, 8),             # 海象运算符
    "dict_union": (3, 9),         # 字典合并运算符 |
    "structural_match": (3, 10),  # 结构化模式匹配
    "exception_group": (3, 11),   # 异常组
    "type_params": (3, 12),       # type 语句与泛型语法
    "free_threaded": (3, 13),     # 自由线程构建
}

def supported(feature: str) -> bool:
    """检查当前解释器是否支持指定特性"""
    required = CAPABILITIES[feature]
    return sys.version_info[:2] >= required

for name in CAPABILITIES:
    mark = "支持" if supported(name) else "不支持"
    print(f"{name:<18} {mark}")
text
walrus             支持
dict_union         支持
structural_match   支持
exception_group    支持
type_params        支持
free_threaded      不支持

示例三:识别并替换过时写法 ​

下表列出了常见的老式写法与其现代替代:

过时写法现代写法引入版本
typing.List[int]list[int]3.9
typing.Dict[str, int]dict[str, int]3.9
typing.Optional[int]int | None3.10
typing.Union[int, str]int | str3.10
"{}".format(x)f"{x}"3.6
显式泛型 TypeVarclass C[T]:3.12
os.path.join 拼接pathlib.Path / "x"3.6 起流行
python
# 现代写法示例(Python 3.12+)
from pathlib import Path

type Id = int
type UserMap = dict[Id, str]

def find_user(users: UserMap, user_id: Id) -> str | None:
    """按 ID 查找用户,找不到返回 None"""
    return users.get(user_id)

def file_size(path: str) -> int:
    """返回文件字节大小,路径用 pathlib 统一处理"""
    target = Path(path) / "report.txt"
    return target.stat().st_size if target.exists() else 0

print(find_user({1: "alice", 2: "bob"}, 2))
print(find_user({1: "alice"}, 99))
print(file_size("."))
text
bob
None
0

注意事项 ​

  • 不要使用已 EOL 的版本:Python 3.8 及更早版本已停止安全支持,存在未修复漏洞风险。
  • 注意版本引入时机:match 需 3.10+,type 语句需 3.12+,写库时要考虑用户环境。
  • 预发布版不适合生产:alpha/beta/rc 版本 API 可能变动,仅在测试环境体验。
  • free-threaded 是实验特性:需要专门安装,且部分 C 扩展仍不兼容。
  • sys.version_info 比较用元组:sys.version_info[:2] >= (3, 11),不要用字符串比较。
  • Python 2 代码不要直接运行:print "x" 在 Python 3 中是语法错误,需先做迁移。

最佳实践 ​

  • 新项目统一使用 Python 3.12+:享受类型参数、性能优化与现代错误提示。
  • 用 pyproject.toml 声明最低版本:通过 requires-python = ">=3.11" 明确支持范围。
  • 在 CI 中测试多个版本矩阵:确保声明支持的版本都真实可用。
  • 关注官方 What's New 文档:每次升级前阅读对应版本的新特性与不兼容变更。
  • 用工具自动升级语法:pyupgrade、ruff 的 UP 规则可批量替换过时写法。
  • 为依赖设定安全更新策略:定期检查依赖的 Python 版本支持情况,避免被 EOL 拖累。
bash
# 用 pyupgrade 把老式 typing 写法批量升级到现代语法
pip install pyupgrade
pyupgrade --py312-plus src/**/*.py

# 用 ruff 检查并自动修复过时语法
ruff check --select UP --fix src/

下一节

继续学习:CPython 解释器原理

参考链接 ​