模块 3 - 函数与 Pythonic 写法 · 第 13 课
作用域、模块与 import
理解名称查找、文件模块和导入方式,组织可复用的实验代码。
局部与全局作用域
learning_rate = 1e-3
def show_rate():
local_name = "demo"
print(learning_rate, local_name)
show_rate()
函数调用时会创建局部作用域。函数可以读取外部名称(global lookup),但函数内创建的 local_name 只在函数执行期间存在;调用结束后,直接访问它会得到 NameError。优先通过参数传值、通过返回值传出,少用 global 修改外部状态:
learning_rate = 1e-3
def scaled_rate(factor):
temporary = learning_rate * factor
return temporary
assert scaled_rate(10) == 0.01
这里 learning_rate 是查找到的全局名称,factor 和 temporary 是局部名称;返回值把结果带回调用者。
模块就是可导入的文件
模块就是一个 Python 文件。把函数放在 metrics.py 后,另一个文件可以写。下面假设两个文件与终端当前目录相同。
# metrics.py
def accuracy(predictions, labels):
correct = sum(prediction == label for prediction, label in zip(predictions, labels))
return correct / len(labels)
示例假设 predictions 和 labels 长度一致;长度校验会在后面的异常课程中处理。
# train.py,与 metrics.py 同目录
from metrics import accuracy
predictions = [1, 0, 1]
labels = [1, 1, 1]
print(accuracy(predictions, labels))
在该目录运行 python train.py,预期输出 0.6666666666666666。from metrics import accuracy 只导入函数;也可以写 import metrics 后使用 metrics.accuracy(...),后者更清楚地显示名称来自哪个模块。
__name__ 入口保护
可执行模块常写:
def main():
print("run experiment")
if __name__ == "__main__":
main()
直接运行文件时会调用 main();被其他文件导入时不会自动运行。这能避免导入工具函数时意外启动实验。
练习
★ 基础:作用域阅读
预测 show_rate() 打印什么,并说明 local_name 为什么不能在函数外直接读取。
★★ 应用:模块边界
按上面的 metrics.py 和 train.py 文件边界运行一次,确认导入函数后能得到准确率。再把 import 改为 import metrics,保持输出不变。
★★★ 综合:入口保护
在 metrics.py 增加 main(),分别测试直接运行和被导入两种行为。D2L 项目通常把数据、模型和训练工具拆在不同模块中;清晰的 import 是阅读大型代码的入口。