Python 进阶话题

1. PEP(Python Enhancement Proposal)

PEP 是 “Python Enhancement Proposal” 的缩写,中文通常叫”Python 增强提案”。

它是一份设计文档,用来向 Python 社区提出:

  • 新语言特性
  • 标准库新增/修改
  • 开发流程、编码规范、发布策略等改进

每份 PEP 先由作者公开草案,经 python-dev 邮件列表充分讨论,最后由 Python Steering Council 决定是否接受。

重要 PEP 速查表

发号名称引入版本一句话作用
语言语法
PEP 8Style Guide for Python Code2001社区最广泛遵循的代码格式与命名规范
PEP 492async / await 语法3.5把协程做成一等语法,实现高效 I/O 并发
PEP 572海象运算符 :=3.8在表达式内完成赋值,减少重复求值
PEP 634结构化模式匹配 (match-case)3.10类似 switch,但支持解构与守卫条件
类型提示
PEP 484Type Hints3.5引入函数注解+ typing 模块
PEP 526变量注解语法3.6给类属性、全局/局部变量也加上类型提示
PEP 585内置泛型 (list[int])3.9不再必须从 typing 引入 List Dict 等
PEP 604联合类型简写 (str | int)3.10用 | 代替 Union
PEP 544Protocol(静态”鸭子类型”)3.8无需继承即可描述对象接口
数据与性能
PEP 448更通用解包3.5允许 {**d1, **d2}、[*a, *b] 等写法
PEP 557Data Classes3.7用 @dataclass 自动生成样板代码
构建与发布
PEP 440版本号统一规范2013规定版本号格式
PEP 517/518构建后端隔离3.6+允许用非 setuptools 工具打包
并发与并行
PEP 3156asyncio 框架3.4统一事件循环、Future/Task 模型
PEP 525/530异步生成器/异步推导式3.6/3.7让 yield 与 for 也能在协程里高效工作

2. __init__.py 文件

__init__.py 文件是 Python 包中的一个特殊文件,它有几个重要作用:

2.1 标识目录为 Python 包

  • 当 Python 解释器看到一个目录中包含 __init__.py 文件时,它会将该目录视为一个 Python 包
  • 没有 __init__.py 的目录只是一个普通目录,不能被导入为包

2.2 执行包初始化代码

  • 当包或包中的模块被导入时,__init__.py 文件会自动执行
  • 可以在这里设置包级别的变量、导入必要的模块或执行初始化操作

2.3 控制包的导入行为

  • 通过在 __init__.py 中定义 __all__ 变量,可以控制 from package import * 的行为
  • 可以在 __init__.py 中导入子模块,使它们在包级别可用

2.4 示例

# __init__.py
"""这是一个示例包"""
 
__version__ = "1.0.0"
__all__ = ["function1", "Class1"]
 
from .module1 import function1
from .module2 import Class1
 
print("包已初始化")

2.5 Python 3.3+ 的变化

  • 在 Python 3.3 之后,有了命名空间包(不需要 __init__.py
  • 但传统包仍然推荐使用 __init__.py

3. Runnable 概念

Runnable 并非 Python 内置关键字或类,而是 并发编程中的概念,指代”可被线程执行的任务/代码逻辑”。

3.1 函数作为 Runnable

import threading
 
def task(name: str):
    print(f"Task {name}")
 
thread = threading.Thread(target=task, args=("A",))
thread.start()
thread.join()

3.2 类作为 Runnable

import threading
 
class MyTask(threading.Thread):
    def __init__(self, name: str):
        super().__init__()
        self.name = name
 
    def run(self):
        print(f"Task {self.name}")
 
task = MyTask("A")
task.start()
task.join()

3.3 Runnable vs 协程

特性Runnable(线程)协程
调度方式内核态抢占式用户态协作式
切换开销较大极小
适用场景I/O + CPU 密集型I/O 密集型

4. 数据类(dataclass)

PEP 557 引入,Python 3.7+ 支持:

from dataclasses import dataclass
 
@dataclass
class Person:
    name: str
    age: int
    email: str = ""
 
p = Person("Alice", 30)
print(p)  # Person(name='Alice', age=30, email='')

自动生成 __init____repr____eq__ 等方法。


5. 海象运算符(:=)

PEP 572 引入,Python 3.8+ 支持:

# 在表达式内赋值
if (n := len(data)) > 10:
    print(f"数据太长: {n} 个元素")
 
# 避免重复调用
while (line := file.readline()) != "":
    process(line)

6. 结构化模式匹配

PEP 634 引入,Python 3.10+ 支持:

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case 401 | 403 | 407:
            return "Not allowed"
        case _:
            return "Something's wrong"

解构匹配

point = (1, 2)
 
match point:
    case (0, 0):
        print("Origin")
    case (0, y):
        print(f"Y axis: {y}")
    case (x, 0):
        print(f"X axis: {x}")
    case (x, y):
        print(f"Point: ({x}, {y})")