第二章|函数、作用域与闭包
本章目标
深入理解 Python 函数机制:如何定义和调用函数、作用域规则、闭包的工作原理、灵活的参数模型。
从基本的函数定义开始,理解 LEGB 作用域规则,掌握闭包的状态封装能力,最后学习 Python 强大而灵活的参数系统。
学习路径
按顺序阅读以下文章,每篇包含讲解、示例和练习:
函数:定义、参数、返回值与调用
学习函数定义、参数传递、返回值、默认参数值、文档字符串、lambda 表达式。作用域与 LEGB:函数如何找到名字
理解 LEGB 作用域规则、全局与本地变量、global 和 nonlocal 关键字。闭包:捕获外层变量与生命周期
掌握闭包概念、变量捕获机制、闭包应用场景、闭包 vs 类的选择。参数模型:位置、关键字、解包与默认值陷阱
学习 *args、**kwargs、参数解包、仅限位置/关键字参数、避免默认参数陷阱。
关键概念
函数是一等对象
Python 中函数是一等对象,可以赋值给变量、作为参数传递、从函数返回。这是函数式编程和装饰器的基础。
def square(x):
return x * x
f = square # 函数赋值
print(f(5)) # 25
def apply(func, value):
return func(value) # 函数作为参数
print(apply(square, 3)) # 9LEGB 规则
Python 按 Local → Enclosing → Global → Built-in 顺序查找名字。理解这个规则是掌握作用域的关键。
闭包
闭包是捕获了外层作用域变量的函数。即使外层函数返回,闭包仍可访问被捕获的变量。闭包用于状态封装、工厂函数、回调等场景。
def make_counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
counter = make_counter()
print(counter()) # 1
print(counter()) # 2灵活的参数系统
Python 的参数系统支持:
- 位置参数和关键字参数
*args收集任意位置参数**kwargs收集任意关键字参数/标记仅限位置参数(Python 3.8+)*标记仅限关键字参数
这使得 Python 函数极其灵活,但也需要理解默认参数的陷阱。
前置知识
- 第一章:值、绑定与控制流
- 理解对象与名字绑定
- 掌握基本控制流
后续章节
完成本章后,继续学习:
第三章:对象、集合与文本数据
深入列表、字典、集合、字符串、Unicode、正则表达式、日期时间、序列化。第四章:类、继承与对象协议
理解类定义、继承、特殊方法、描述符、数据类。
练习答案
本章所有练习的答案和详细解释:第二章练习答案
深入阅读
为什么函数是一等对象很重要?
函数作为对象使得高阶函数、装饰器、回调等模式成为可能。这是 Python 函数式编程能力的基础,也让代码更灵活、可复用。
何时用闭包,何时用类?
闭包适合:
- 简单的状态封装(1-2 个变量)
- 工厂函数
- 回调函数
类适合:
- 复杂的状态和行为
- 多个相关方法
- 需要继承或多态
默认参数陷阱的根本原因
默认参数在函数定义时求值一次,而非每次调用时。可变对象(列表、字典)作为默认值时,所有调用共享同一对象。使用 None 作为哨兵值,在函数体内创建新对象。
global vs nonlocal
global:声明使用模块级全局变量nonlocal:声明使用最近的外层函数变量(不包括全局)
两者都用于在嵌套作用域中修改外层变量。只读取不需要声明。
返回Python 学习路线 · 开始第一节