总结速览
| 特性 | Python 3.6 | Python 3.7 | 主要变化 |
|---|---|---|---|
| 发布日期 | 2025年12月23日 | 2025年6月27日 | 7 是 3.6 的后续稳定版本 |
| PEP 498 | ✅ | ✅ | 引入了 f-string (格式化字符串字面量),极大地简化了字符串格式化 |
| PEP 515 | ✅ | ✅ | 允许在数字字面量中使用下划线,如 1_000_000,提高可读性 |
| PEP 525/530 | ❌ | ✅ | 引入了 异步生成器 和 异步推导式 (如 async for, async with) |
| PEP 562 | ❌ | ✅ | 允许 __getattr__ 在模块级别使用,实现了更灵活的动态属性访问 |
| PEP 563 | ❌ | ✅ | 引入了 “后置类型注解” (Postponed Evaluation of Annotations),将 from __future__ import annotations 变为默认行为 |
| PEP 557 | ❌ | ✅ | 引入了 dataclasses,这是一个非常受欢迎的装饰器,用于简化类创建 |
| 性能 | 基准测试显示有显著提升 | 在 3.6 的基础上进一步优化 | 7 在字典操作、异步IO等方面性能更好 |
| 默认编码 | UTF-8 (推荐,但平台依赖) | 平台无关的 UTF-8 | 解决了 3.6 及之前版本在不同平台下默认编码不一致的问题 |
asyncio |
引入了 asyncio,但功能相对基础 |
asyncio 成为标准库的一部分,并得到重大增强 |
7 的 asyncio 更稳定、更强大,是“一等公民” |
contextlib |
- | 引入了 asynccontextmanager |
支持异步上下文管理器,与 asyncio 配合更佳 |
核心差异详解
异步编程 (asyncio) 的飞跃 (最重要的变化之一)
这是 Python 3.7 相对于 3.6 最大的进步之一,在 3.6 中,asyncio 虽然已经存在,但 3.7 对其进行了“稳定化”和“标准化”处理。

- Python 3.6:
asyncio被认为是实验性的,虽然可以使用,但 API 和最佳实践仍在不断变化中。 - Python 3.7:
asyncio不再是实验性的,它被正式确立为 Python 核心功能的一部分,并进行了大量优化和功能增强,- 引入了
asyncio.run()函数,使得编写异步程序的主入口变得异常简单。 asyncio的任务调度、事件循环管理等核心组件都经过了性能和稳定性的提升。
- 引入了
代码示例对比:
- Python 3.6 风格 (相对繁琐)
# Python 3.6
import asyncio
async def my_coroutine():
print("Hello")
await asyncio.sleep(1)
print("World")
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(my_coroutine())
finally:
loop.close()
- Python 3.7 风格 (简洁优雅)
# Python 3.7
import asyncio
async def my_coroutine():
print("Hello")
await asyncio.sleep(1)
print("World")
# 一行代码即可运行协程
asyncio.run(my_coroutine())
类型注解的进化
Python 3.6 引入了类型注解,但 3.7 对其进行了关键改进。
- PEP 563: Postponed Evaluation of Annotations (后置类型注解)
- Python 3.6: 类型注解在定义时就被立即求值,这会导致一个问题:如果类型注解中引用了尚未定义的类(在类方法中返回该类本身),就会导致
NameError。 - Python 3.7: 默认启用了后置求值,这意味着类型注解不会被立即求值,而是作为字符串存储,这解决了循环引用的问题,并允许更灵活的类型定义,如果你想在 3.7 中恢复旧的行为,可以显式地
from __future__ import annotations。
- Python 3.6: 类型注解在定义时就被立即求值,这会导致一个问题:如果类型注解中引用了尚未定义的类(在类方法中返回该类本身),就会导致
代码示例:
# Python 3.6 和 3.7 (未启用 PEP 563 时会报错)
class Node:
def __init__(self, value: 'Node', next_node: 'Node' = None):
self.value = value
self.next_node = next_node
# 在 Python 3.7 中,这可以正常工作,因为类型注解是后置求值的。
dataclasses 的引入 (PEP 557)
这是 Python 3.7 带来的一个“杀手级”功能,极大地简化了数据类的创建。

- Python 3.6: 你需要手动编写
__init__,__repr__,__eq__等方法来创建一个简单的数据容器。 - Python 3.7: 引入了
@dataclass装饰器,可以自动生成这些方法。
代码示例对比:
- Python 3.6 风格 (样板代码多)
# Python 3.6
from typing import Optional
class Person:
def __init__(self, name: str, age: Optional[int] = None):
self.name = name
self.age = age
def __repr__(self):
return f"Person(name={self.name!r}, age={self.age!r})"
def __eq__(self, other):
if not isinstance(other, Person):
return NotImplemented
return (self.name, self.age) == (other.name, other.age)
- Python 3.7 风格 (极其简洁)
# Python 3.7
from dataclasses import dataclass
from typing import Optional
@dataclass
class Person:
name: str
age: Optional[int] = None
# __init__, __repr__, __eq__ 等方法都已自动生成!
p1 = Person("Alice", 30)
p2 = Person("Bob")
print(p1) # 输出: Person(name='Alice', age=30)
print(p1 == p2) # 输出: False
模块级 __getattr__ (PEP 562)
这个功能允许你动态地为模块添加属性,而无需创建 __init__.py 文件中的复杂逻辑,这在创建插件系统或包装其他库时非常有用。
- Python 3.6: 只能在类上使用
__getattr__。 - Python 3.7: 可以在模块级别定义
__getattr__函数。
默认编码的统一
这是一个底层的但非常重要的修复,在 Python 3.6 及之前版本,文件系统编码和标准流编码在不同操作系统上可能不一致(Windows 上是 mbcs,Linux/macOS 上是 UTF-8),这可能导致跨平台代码出现意外行为。
- Python 3.7: 明确将标准库和文件系统 API 的默认编码统一为 UTF-8,无论在什么平台上运行,行为都更加可预测。
如何选择?
-
新项目应该选择 Python 3.7 或更高版本。
- 它提供了更现代、更强大、更稳定的异步编程能力。
dataclasses等新特性会显著提升开发效率。- 类型注解系统更完善,有助于大型项目的维护。
- 已于 2025 年 6 月 23日停止支持,强烈不建议用于生产环境。
-
维护旧项目时,你可能会遇到 Python 3.6。
- 如果项目依赖的第三方库尚未支持 3.7,或者项目本身使用了 3.7 才有的特性(如
dataclasses),那么你需要保持 3.6。 - Python 3.6 也已于 2025 年 12 月 23日停止支持,同样不建议用于生产环境。
- 如果项目依赖的第三方库尚未支持 3.7,或者项目本身使用了 3.7 才有的特性(如
-
升级建议:
- 如果你的项目仍在使用 Python 3.6,应尽快升级到 Python 3.8 或更高版本(如 3.9, 3.10, 3.11, 3.12),升级路径通常是
6 -> 3.7 -> 3.8 -> ...,每次升级都会有兼容性修复和性能提升,升级时,主要需要注意asyncioAPI 的变化(如果你深度使用它)以及dataclasses的引入可能会覆盖你手写的类似方法。
- 如果你的项目仍在使用 Python 3.6,应尽快升级到 Python 3.8 或更高版本(如 3.9, 3.10, 3.11, 3.12),升级路径通常是
