← 返回 Day 14 正文

Day 14 · 练习与清单

检查清单与练习题

Day 014: 模块与包


✅ 今日完成清单

模块基础

模块缓存

name == 'main' 原理

包结构

相对导入与绝对导入

pycache 与字节码

实战

避坑


📝 练习题

练习 1:编写一个可重用的倒计时模块

编写一个模块 countdown.py,提供以下功能:

python
# 期望用法
from countdown import countdown, countdown_str

print(countdown_str(3))   # → ['3', '2', '1', 'Go!']
# countdown(5)            # → 5... 4... 3... 2... 1... Go!(每秒打印)

进阶要求:在另一个文件中 import countdown,验证自测试代码不被执行。


练习 2:创建一个科学计算包

创建一个 scicalc/ 包,包含以下结构:

scicalc/
├── __init__.py
├── arithmetic.py     ← 基础运算(add, subtract, multiply, divide)
├── geometry.py       ← 几何计算(circle_area, rectangle_area, triangle_area)
└── statistics.py     ← 统计计算(mean, median, variance)

要求: - __init__.py 中重导出所有公开函数 - statistics.py 使用相对导入引入 arithmetic.py 中的 divide 函数(用于计算均值) - 每个子模块包含 __all__ 控制 - 编写一个 main.py 使用该包


练习 3:排查循环导入

给定以下两个模块:

python
# employee.py
from department import get_department_name

class Employee:
    def __init__(self, name, dept_id):
        self.name = name
        self.dept_id = dept_id
    
    def info(self):
        return f"{self.name} 属于 {get_department_name(self.dept_id)}"

# department.py
from employee import Employee

class Department:
    def __init__(self, id, name):
        self.id = id
        self.name = name
        self.employees = []
    
    def add_employee(self, name):
        emp = Employee(name, self.id)
        self.employees.append(emp)
        return emp

def get_department_name(dept_id):
    names = {1: "工程部", 2: "市场部", 3: "财务部"}
    return names.get(dept_id, "未知")

要求: 1. 运行代码,观察发生的错误类型 2. 使用 延迟导入 修复循环导入问题 3. 使用 提取公共模块 的方式重构(提示:将 get_department_name 移到新文件)


练习 4:实现一个插件发现系统

编写一个模块 plugin_loader.py,能够: 1. 扫描 plugins/ 目录下的所有 .py 文件 2. 动态导入每个模块 3. 检查每个模块是否有一个 run() 函数 4. 收集所有有效的 run() 函数并执行

python
# plugins/hello.py
def run():
    print("Hello Plugin!")

# plugins/calculator.py
def run():
    print("Calculator Plugin: 2 + 3 = 5")

# plugin_loader.py 的期望行为
# python3 plugin_loader.py
# → 发现 2 个插件
# → 运行 hello.run() → "Hello Plugin!"
# → 运行 calculator.run() → "Calculator Plugin: 2 + 3 = 5"

提示:使用 importlib、os.listdir()、动态 import() 或 __import__()。


练习 5:调试 pycache 异常

描述以下场景中可能发生的问题,并给出解决方案:

场景 A:团队项目中,Alice 用 Python 3.11 运行了模块,生成了 __pycache__/。Bob 用 Python 3.12 运行时遇到了一个奇怪的错误。错误原因是什么?如何修复?

场景 B:部署到服务器时,运维人员删除了所有 .py 文件但保留了 __pycache__/。这会导致什么问题?

场景 C:一个模块被两种不同的路径导入(例如通过 sys.path 中的两个等效路径),导致模块被加载两次,状态不一致。这是为什么?如何解决?


📊 自我评估

知识点 理解程度 (1-5) 备注
import 四种写法 ⚪⚪⚪⚪⚪
sys.path 搜索路径 ⚪⚪⚪⚪⚪
sys.modules 缓存 ⚪⚪⚪⚪⚪
name == 'main' ⚪⚪⚪⚪⚪
包与 init.py ⚪⚪⚪⚪⚪
绝对导入 ⚪⚪⚪⚪⚪
相对导入 ⚪⚪⚪⚪⚪
all 控制 ⚪⚪⚪⚪⚪
pycache 字节码 ⚪⚪⚪⚪⚪
循环导入排查 ⚪⚪⚪⚪⚪
实战:工具包构建 ⚪⚪⚪⚪⚪

😊 完成练习题后,标记检查清单的对应项,并在自我评估中打分。