Week 2 学习计划|Python 函数、作用域、闭包与模块化
Week 2 学习计划:函数、作用域、闭包与模块化,从参数组合、闭包、decorator 简化版到自定义 module,并把 Week 1 项目重构为 core/storage/cli/config 并加入 dataclass、type hints、logging。
本周计划对应一年学习计划总纲 Phase I 的 Week 2 · 函数、作用域、闭包与模块化,按总纲 Part II「每周固定执行模板」编排。计划篇只保留任务与要求,实际产出见 Week 2 学习成果。
🎯 本周目标
L1
- 能理解并使用 function / parameter / default argument /
*args/**kwargs/ scope / closure / lambda / import / module / package。
L2
- 手写参数组合、闭包、decorator 简化版、自定义 module;并把 Week 1 项目重构为
core//storage//cli//config/,加入 dataclass、type hints、logging。
L3
- (总纲本周等级为 L2,不设 L3)
📚 Core Knowledge
总纲 Week 2 学习内容:
function / parameter / default argument / *args / **kwargs / scope / closure / lambda / import / module / package。
- More on Defining Functions:positional / keyword / default 参数、
*args/**kwargs、lambda - Scopes and Namespaces:LEGB、global / nonlocal、闭包
- 模块与包:import、module、package、
__name__ - dataclasses、typing、logging:服务本周的重构任务
✍️ Human Core
总纲 Week 2 要求手写:
- 参数组合
- 闭包
- decorator 简化版
- 自定义 module
按日拆解如下(每天 1.5–2h:学习 45min → 实验 45min → 验收 15min)。
Day 1|函数进阶:参数、作用域、闭包(1.5–2h)
学习 45min:阅读 More on Defining Functions 与 Scopes and Namespaces,掌握 positional / keyword / default 参数、*args / **kwargs、可变默认参数陷阱、LEGB、global / nonlocal、闭包、函数是一等对象、lambda。
实验 45min:创建 function_demo.py:
- 参数组合:positional / keyword / default 三种传参方式
- 可变默认参数陷阱:
def append_to(item, target=[]):
target.append(item)
return target
print(append_to(1))
print(append_to(2))
print(append_to(3, []))
写出三次输出并解释原因,再用 target=None 修复。
- 闭包计数器
make_counter():得到 1、2、3,并验证两个计数器相互独立 - decorator 简化版:写一个简易装饰器,包住一个函数,在调用前后打印日志,理解“函数作为参数传入、返回新函数”与闭包的关系
- lambda:构造
(name, age, score)数据,用 lambda 多字段排序
验收 15min:不用资料解释默认参数何时求值、为什么 list 默认值危险、*args 和 **kwargs 有什么区别、闭包捕获的是值还是变量、“函数是对象”意味着哪三件事。
Day 2|自定义 module 与包(1.5–2h)
学习 45min:阅读 Modules 与 Packages,掌握 module / package / subpackage、三种 import、__name__ == "__main__"、re-export、sys.path / sys.modules、循环导入。
实验 45min:创建包结构:
mypkg/
├── __init__.py
├── core.py
└── utils/
├── __init__.py
└── text.py
- 三种 import:
import mypkg.core、from mypkg import core、from mypkg.core import xxx - 自定义 module:在
mypkg/core.py中编写自己的函数模块,并用 re-export 让from mypkg import xxx可直接使用 - 模块运行方式:
python core.py与python -m mypkg.core观察__name__差异 - 循环导入:人为制造
a.py → import b、b.py → import a,观察错误并修复
验收 15min:回答 import 同一模块两次代码执行几次及为什么、python file.py 和 python -m pkg.mod 的区别、循环导入为什么发生、最常见解决思路。
Day 3|闭包与作用域深化(1.5–2h)
学习 45min:深入 LEGB、闭包捕获规则、global / nonlocal 的边界,重点吃透总纲那条验收:
x = outer()
x()
为什么 x() 还能访问 outer() 中定义的变量。
实验 45min:
def outer():
n = 0
def inner():
nonlocal n
n += 1
return n
return inner
x = outer()
print(x()) # 1
print(x()) # 2
解释闭包如何“记住”定义时的环境,以及 nonlocal 在其中起什么作用。
验收 20min:不用资料解释为什么 x() 还能访问 outer() 里的变量。
Day 4|decorator 简化版(1.5–2h)
学习 45min:理解 decorator 本质是“接受函数、返回新函数”的高阶函数,依赖闭包保存原函数。
实验 45min:
def log(func):
def wrapper(*args, **kwargs):
print(f"call {func.__name__} args={args} kwargs={kwargs}")
return func(*args, **kwargs)
return wrapper
@log
def add(a, b):
return a + b
验证装饰后 add(1, 2) 会先打印日志再返回 3。理解 @log 等价于 add = log(add)。
验收 15min:解释 @log 做了什么事、为什么需要 *args / **kwargs、装饰器与闭包的关系。
Day 5|L2 重构(一):目录拆分 + logging(1.5–2h)
学习 45min:阅读 logging 文档与 Logging HOWTO,掌握 Logger、Handler、Formatter、日志级别、logging.getLogger(__name__)、basicConfig;学习分层思想 storage → core → cli 与 config。
实验 45min:
- 目录拆分:把 Week 1 项目重构为:
project/
├── app/
│ ├── __init__.py
│ ├── core/
│ ├── storage/
│ ├── cli.py
│ └── config.py
├── tests/
└── config.json
- 配置与代码分离:创建
config.json,用 dataclassAppConfig实现load_config() - logging:用
logging.getLogger(__name__)替换print,统一格式(时间、模块、级别、消息) - 测试:保持原有测试可运行
重点实验(basicConfig):分别在 storage、cli 调用 logging.basicConfig(...),总结 basicConfig() 应由入口统一配置。
验收 15min:回答四层结构分别负责什么、为什么推荐 getLogger(__name__)、哪些东西应 / 不应放配置文件、什么信号说明“拆对了”与“越拆越乱”。
Day 6|L2 重构(二):dataclass 与 type hints(1.5–2h)
学习 45min:阅读 dataclasses 与 typing 文档,掌握 @dataclass、field、default_factory、frozen=True,以及变量 / 参数 / 返回值标注、Optional、Union、list[T]、dict[K, V]。
实验 45min:
- 为重构后的项目定义 dataclass 数据模型(如
AppConfig、Record),可变字段用default_factory - type hints:给 storage、core 的公开函数补全参数与返回值类型标注
- 运行 mypy 检查类型标注(作为重构的验证手段)
验收 15min:回答 @dataclass 自动生成哪些方法、list[str] 为什么不能直接作默认值及正确写法、Optional[int] 什么意思、类型标注会不会自动阻止错误运行。
Day 7|重构验收(1.5–2h)
Part 1|重构验收 60min:确认重构后的 Week 1 项目:目录已拆为 core/ / storage/ / cli/ / config/,dataclass、type hints、logging 均已接入,原测试全部通过。
Part 2|周复盘 45min:回答总纲验收——x = outer(); x() 为什么还能访问 outer() 中定义的变量;并记录本周手写的参数组合、闭包、decorator 简化版、自定义 module 各自产出在哪个文件。
🤖 AI Build
总纲 Week 2 要求:将 Week 1 重构为 core/、storage/、cli/、config/,并加入 dataclass、type hints、logging。
- 目录重构为
core//storage//cli//config/ - 加入 dataclass
- 加入 type hints
- 加入 logging
🧪 Experiment
Hypothesis
- 通过目录拆分、dataclass、type hints 与 logging,Week 1 项目能在不改变对外行为的前提下变得可维护、可测试。
Experiment
- 将 Week 1 的 KV 项目按职责拆为 storage / core / cli / config 四层,接入 logging 与
config.json,补充 dataclass 与类型标注,并用 pytest 验证行为不变。
Result
- 结论与详细记录见 Week 2 学习成果。
Conclusion
- 重构在不改变行为的前提下提升了可维护性;
basicConfig只在入口调一次。
📝 数智工程师考试映射
- Python 函数、作用域、闭包与 decorator
- Python 模块与包机制(import、
sys.path、sys.modules) - 代码组织、分层与工程化重构
✅ Acceptance
总纲 Week 2 验收:
L1
- 能独立解释:
x = outer()
x()
为什么还能访问 outer() 中定义的变量。
L2
- 手写参数组合、闭包、decorator 简化版、自定义 module
- 将 Week 1 项目重构为
core//storage//cli//config/,加入 dataclass、type hints、logging
L3
- 总纲本周不设 L3
🧠 本周最重要的问题
为什么
x = outer(); x()还能访问outer()中定义的变量?
❓ 尚未解决
- 待收尾:Week 1 项目重构后的 dataclass / type hints / logging 完整落地与测试
- decorator 简化版已列入本周手写项,需确认产出文件
📊 Final Level
L2
Week 2 最终项目结构
project/
├── app/
│ ├── __init__.py
│ ├── core/
│ │ └── ...
│ ├── storage/
│ │ └── ...
│ ├── cli.py
│ └── config.py
├── tests/
│ └── ...
├── config.json
└── ...
本周产出清单
function_demo.py(参数组合、闭包、decorator 简化版、lambda)mypkg/(自定义 module 与包)- Week 1 项目完成目录拆分
- logging 接入
- 配置文件接入
- dataclass 与 type hints
- mypy 检查通过
来源与延伸阅读
- 01Week 1 学习计划|Python 对象模型与数据结构
- 02一年学习计划:从 Python 到 Data/AI 系统的 52 周
- 03Week 1 学习成果|复杂度实测、对象模型与数据结构实战
- 04Week 2 学习计划|Python 函数、作用域、闭包与模块化
- 05Week 2 学习成果|闭包、decorator 与工程化重构
- 06Week 3 学习计划|异常、测试与 Debugging
- 07Week 3 学习成果|异常、traceback 与 Debug 起步
- 08Week 4 学习成果|Big-O 与四类基础算法
- 09Week 5 学习成果|Stack、Queue 与 MinHeap
- 10Week 6 学习成果|图算法与 Python Engineering Toolkit