杰瑞科技汇

python3.7和python3.6

总结速览

特性 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 对其进行了“稳定化”和“标准化”处理。

python3.7和python3.6-图1
(图片来源网络,侵删)
  • 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 和 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 带来的一个“杀手级”功能,极大地简化了数据类的创建。

python3.7和python3.6-图2
(图片来源网络,侵删)
  • 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日停止支持,同样不建议用于生产环境
  • 升级建议:

    • 如果你的项目仍在使用 Python 3.6,应尽快升级到 Python 3.8 或更高版本(如 3.9, 3.10, 3.11, 3.12),升级路径通常是 6 -> 3.7 -> 3.8 -> ...,每次升级都会有兼容性修复和性能提升,升级时,主要需要注意 asyncio API 的变化(如果你深度使用它)以及 dataclasses 的引入可能会覆盖你手写的类似方法。
分享:
扫描分享到社交APP
上一篇
下一篇