
文章目录
- 📖 开篇导读
- 🎯 学习目标
- 📚 知识点理论精讲
-
- 一、作用域(Scope)的基本概念
- 二、局部变量(Local Variable)
-
- 局部变量的生命周期
- 三、全局变量(Global Variable)
-
- 3.1 读取全局变量
- 3.2 修改全局变量:`global`关键字
- 3.3 何时使用全局变量
- 四、LEGB规则详解
-
- 4.1 各层级示例
- 4.2 屏蔽效应
- 4.3 内置作用域示例
- 五、嵌套函数与`nonlocal`关键字
-
- 5.1 访问外层变量(只读)
- 5.2 修改外层变量:`nonlocal`
- 5.3 多层嵌套
- 六、闭包(Closure)基础
-
- 6.1 闭包的形成条件
- 6.2 闭包的作用
- 6.3 查看闭包中的变量
- 6.4 常见误区:循环中创建闭包
- 七、作用域与变量生存周期
- 💻 代码案例实操
-
- 案例1:局部变量与全局变量基础演示
- 案例2:LEGB规则完整演示
- 案例3:`nonlocal`深入理解
- 案例4:闭包实现计数器
- 案例5:闭包实现简单的缓存(记忆化)
- 案例6:循环闭包陷阱及解决
- 案例7:实际工作场景——配置管理
- ⚠️ 易错点避坑总结
- 📝 课后实战练习题
-
-
- 第1题:全局与局部变量分析
- 第2题:正确使用`global`
- 第3题:嵌套函数与`nonlocal`
- 第4题:闭包实现简单的平均值计算器
- 第5题:循环闭包陷阱修复
- 第6题:LEGB查找顺序验证
- 第7题:综合应用——带重置功能的计数器
-
- 🧠 知识点思维导图总结
- 🔜 下节课预告
-
- 第14课:高阶函数、lambda匿名函数、map/filter/sorted内置高阶函数实战
- 🔗《50节课 Python 从入门到精通》系列课程导航
📖 开篇导读
前面两节课我们学习了函数的定义、参数传递的各种花样。但你有没有想过:函数内部定义的变量,在函数外面能访问吗?不同函数之间的变量会互相影响吗?为什么有些变量在函数内部修改后,外面的值却没有变化?这些问题的答案,都藏在作用域这个概念中。
作用域(Scope)就是变量的“可见范围”。理解作用域,你才能写出预期正确的代码,避免“明明改了变量却没变”的诡异bug。此外,闭包(Closure) 是作用域概念的延伸,也是装饰器、函数式编程的基础,面试中经常出现。
💡 工作场景:当你需要在一个函数中记住某些状态(比如计数器、缓存),但又不想用全局变量时,闭包就是最佳解决方案。很多框架和库的内部实现都大量使用了闭包。
本课我们将深入讲解:
- 局部变量与全局变量的区别及使用
- global和nonlocal关键字的作用
- LEGB作用域查找规则
- 闭包的概念与简单应用
学完本课,你将能够精准控制变量的作用范围,写出更安全、更模块化的代码。
🎯 学习目标
| 1️⃣ | 理解局部变量和全局变量的区别 | 避免命名冲突,写出清晰代码 |
| 2️⃣ | 掌握global关键字在函数内修改全局变量 | 必要情况下修改全局状态 |
| 3️⃣ | 理解LEGB规则(Local, Enclosing, Global, Built-in) | 面试高频,排查变量查找问题 |
| 4️⃣ | 掌握nonlocal关键字修改嵌套函数中的外层变量 | 闭包进阶必备 |
| 5️⃣ | 理解闭包的概念、形成条件及应用场景 | 装饰器基础,面试常考 |
🔥 面试考点:“Python中变量的作用域有哪些?”“global和nonlocal的区别?”“什么是闭包?闭包有什么好处?”“LEGB顺序是什么?”
📚 知识点理论精讲
一、作用域(Scope)的基本概念
作用域是指变量在程序中可以被访问的范围。Python的作用域是静态的(由代码位置决定),但在运行时动态查找。
Python有四种作用域,按查找顺序(LEGB):
🧠 通俗类比:作用域就像你的居住区域。局部变量就像你家里的物品(只有你家人能直接使用);全局变量就像城市公共设施(所有人都能访问);内置函数就像国家的基础设施(全国通用)。如果你要找一样东西,先从家里找(Local),再到小区(Enclosing),再到城市(Global),最后到国家(Built-in)。
二、局部变量(Local Variable)
在函数内部赋值的变量,作用域仅限于该函数。
def my_func():
x = 10 # 局部变量
print(x)
my_func()
print(x) # NameError: name 'x' is not defined
特点:
- 函数执行时创建,函数返回时销毁
- 不同函数的局部变量互不影响
- 参数也是局部变量
def add(a, b):
result = a + b # result是局部变量
return result
# a, b, result 在函数外部均不存在
局部变量的生命周期
def counter():
count = 0
count += 1
return count
print(counter()) # 1
print(counter()) # 1(每次调用都会重新创建count,不会累加)
如果需要记住多次调用的状态,可以使用全局变量或闭包(后续讲解)。
三、全局变量(Global Variable)
在函数外部(模块顶层)定义的变量,可以被整个模块的所有函数访问(读取),但修改需要特殊声明。
3.1 读取全局变量
g = 100 # 全局变量
def show():
print(g) # 可以读取
show() # 输出100
3.2 修改全局变量:global关键字
在函数内部,如果直接对全局变量赋值,Python会创建一个同名的局部变量,而不是修改全局变量。
g = 100
def modify_wrong():
g = 200 # 这里创建了一个新的局部变量g,全局g不变
print(g) # 200
modify_wrong()
print(g) # 100(全局变量未被修改)
要修改全局变量,必须使用global声明。
def modify_correct():
global g
g = 200 # 现在修改的是全局变量
modify_correct()
print(g) # 200
3.3 何时使用全局变量
- 常量定义:如PI = 3.14159,虽然不是严格不可变,但约定全大写表示常量。
- 配置参数:跨多个函数共享的配置。
- 缓存/计数器:需要在函数调用间保持状态(但更推荐使用闭包或类)。
💡 工作应用:过度使用全局变量会导致代码难以调试和维护,因为任何函数都可能修改它。推荐尽量使用参数传递和返回值,保持函数的“纯度”。
四、LEGB规则详解
当你在代码中使用一个变量时,Python按照Local → Enclosing → Global → Built-in的顺序查找。
4.1 各层级示例
# Built-in: Python内置的函数和异常等
print(len("hello")) # len来自built-in
# Global: 模块级变量
x = "global"
def outer():
# Enclosing: 外层函数变量
y = "enclosing"
def inner():
# Local: 内层函数局部变量
z = "local"
print(x, y, z) # 查找x: 跳过local/enclosing未找到,找到global的x
inner()
outer()
4.2 屏蔽效应
内层作用域的变量会“屏蔽”外层同名的变量。
x = "global"
def func():
x = "local" # 创建局部变量,屏蔽全局
print(x)
func() # local
print(x) # global
4.3 内置作用域示例
# 错误示例:覆盖内置函数
len = 10
print(len("hello")) # TypeError: 'int' object is not callable
# 正确:不要使用内置函数名作为变量名
五、嵌套函数与nonlocal关键字
函数内部可以再定义函数,称为嵌套函数。内层函数可以访问外层函数的变量(即Enclosing作用域),但是不能直接赋值修改,除非使用nonlocal。
5.1 访问外层变量(只读)
def outer():
msg = "Hello"
def inner():
print(msg) # 可以读取外层变量
inner()
outer() # Hello
5.2 修改外层变量:nonlocal
类似于global,但nonlocal用于嵌套函数中修改外层(非全局)的变量。
def outer():
count = 0
def inner():
nonlocal count # 声明count不是局部变量,而是外层函数的变量
count += 1
print(count)
return inner # 返回内部函数(闭包)
f = outer()
f() # 1
f() # 2
🔥 面试考点:“nonlocal和global的区别?”答:global用于修改全局变量;nonlocal用于修改嵌套函数中外层函数的变量(不能是全局)。
5.3 多层嵌套
nonlocal会向上查找最近一层的对应变量(跳过全局)。
def outer():
x = "outer"
def middle():
x = "middle" # 这一层的x
def inner():
nonlocal x # 这里指向middle的x,而不是outer的
x = "inner"
inner()
print("middle:", x)
middle()
print("outer:", x)
outer()
# 输出:
# middle: inner
# outer: outer
六、闭包(Closure)基础
闭包是函数式编程中的一个重要概念。当一个嵌套函数引用了外层函数的变量,并且外层函数返回了这个嵌套函数时,就形成了闭包。闭包让函数可以“记住”其定义时的环境。
6.1 闭包的形成条件
def make_multiplier(factor):
"""返回一个函数,该函数将输入乘以factor"""
def multiplier(x):
return x * factor # 引用外层变量factor
return multiplier
# 创建闭包
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15
6.2 闭包的作用
- 数据隐藏/封装:闭包中的变量不对外暴露,只能通过返回的函数访问。
- 代替小型类:当只需要一个简单状态时,闭包比类更轻量。
- 装饰器的基础:Python装饰器本质就是闭包。
6.3 查看闭包中的变量
闭包会将引用的外层变量保存在__closure__属性中。
def outer():
x = 10
y = 20
def inner():
return x + y
return inner
f = outer()
print(f.__closure__) # 显示闭包信息
print(f.__closure__[0].cell_contents) # 10
print(f.__closure__[1].cell_contents) # 20
6.4 常见误区:循环中创建闭包
# 错误的闭包:共享同一个变量
funcs = []
for i in range(3):
def f():
return i
funcs.append(f)
for f in funcs:
print(f()) # 都输出2,因为i最后变成2,所有f都引用同一个i
# 正确的做法:使用默认参数绑定当前值
funcs = []
for i in range(3):
def f(i=i): # 默认参数将当前i的值绑定
return i
funcs.append(f)
for f in funcs:
print(f()) # 0 1 2
七、作用域与变量生存周期
- 全局变量:从模块加载到程序结束一直存在。
- 局部变量:函数调用时创建,函数返回时销毁。
- 闭包中的外层变量:即使外层函数已经返回,被内层函数引用的变量依然存在(通过闭包保持引用)。
def outer():
value = [0] # 使用列表可变对象,可以在内层函数中修改
def inner():
value[0] += 1
return value[0]
return inner
counter = outer()
print(counter()) # 1
print(counter()) # 2
# value这个列表仍然存在,被闭包引用,不会被销毁
💻 代码案例实操
案例1:局部变量与全局变量基础演示
"""
scope_basic.py
演示局部和全局变量的基本行为
"""
# 全局变量
global_var = 100
def func1():
# 局部变量,与全局同名但不影响
global_var = 200
print("func1内部:", global_var)
def func2():
# 读取全局变量(没有局部同名变量)
print("func2内部:", global_var)
def func3():
# 声明要修改全局变量
global global_var
global_var = 300
print("func3内部修改:", global_var)
print("初始全局:", global_var) # 100
func1() # 200
print("调用func1后全局:", global_var) # 100(未变)
func2() # 100
func3() # 300
print("调用func3后全局:", global_var) # 300
案例2:LEGB规则完整演示
"""
legb_demo.py
演示Local, Enclosing, Global, Built-in的查找顺序
"""
# 全局变量
x = "global x"
def outer():
# Enclosing变量
x = "enclosing x"
def inner():
# Local变量
x = "local x"
print("inner内:", x) # 查找: Local找到
inner()
def inner2():
# 没有局部x,查找Enclosing
print("inner2内:", x) # enclosing x
inner2()
def inner3():
# 使用global关键字强制从全局找
global x
print("inner3内(global):", x) # global x
inner3()
outer()
print("全局:", x) # global x
# 内置作用域示例
import builtins
print(dir(builtins)) # 查看所有内置函数/变量
# 屏蔽内置变量
len = 10
print(len) # 10
# print(len("hi")) # 报错,因为len现在是整数
del len # 删除局部len
print(len("hi")) # 2,恢复内置
案例3:nonlocal深入理解
"""
nonlocal_demo.py
演示nonlocal关键字的使用和多层嵌套
"""
def outer():
count = 0
def increment():
nonlocal count # 声明count来自外层(outer)
count += 1
return count
return increment
counter = outer()
print(counter()) # 1
print(counter()) # 2
def multiple_layers():
a = 10
def middle():
b = 20
def inner():
nonlocal a # 引用middle? 不,nonlocal会跳过局部,找最近的非全局作用域,这里是outer的a
nonlocal b # 引用middle的b
a += 1
b += 1
inner()
print("middle b:", b)
middle()
print("outer a:", a)
multiple_layers()
# 输出:
# middle b: 21
# outer a: 11
案例4:闭包实现计数器
"""
closure_counter.py
使用闭包实现多种计数器
"""
def make_counter(initial=0):
"""返回一个计数器闭包,可以增加、减少、重置"""
count = initial
def increment():
nonlocal count
count += 1
return count
def decrement():
nonlocal count
count -= 1
return count
def reset():
nonlocal count
count = initial
return count
def get():
return count
# 返回包含多个函数的字典或对象
return {"inc": increment, "dec": decrement, "reset": reset, "get": get}
# 创建计数器
c1 = make_counter(10)
print(c1["inc"]()) # 11
print(c1["inc"]()) # 12
print(c1["dec"]()) # 11
print(c1["get"]()) # 11
c1["reset"]()
print(c1["get"]()) # 10
# 创建另一个独立计数器
c2 = make_counter(100)
print(c2["inc"]()) # 101
print(c2["get"]()) # 101
案例5:闭包实现简单的缓存(记忆化)
"""
memoization_closure.py
使用闭包实现函数结果缓存(面试常考)
"""
def memoize(func):
"""装饰器风格的闭包,但这里演示手动闭包"""
cache = {}
def wrapper(*args):
if args not in cache:
print(f"计算 {args} 的结果…")
cache[args] = func(*args)
else:
print(f"从缓存获取 {args} 的结果")
return cache[args]
return wrapper
# 一个耗时的计算函数
def slow_fibonacci(n):
if n < 2:
return n
return slow_fibonacci(n–1) + slow_fibonacci(n–2)
# 使用闭包包装
fib_with_cache = memoize(slow_fibonacci)
print(fib_with_cache(35)) # 第一次,计算较慢
print(fib_with_cache(35)) # 第二次,从缓存快速返回
# 工厂函数:生成带缓存的任意函数
def make_cached(func):
cache = {}
def cached_func(*args):
if args in cache:
return cache[args]
result = func(*args)
cache[args] = result
return result
return cached_func
# 应用于阶乘
def factorial(n):
if n <= 1:
return 1
return n * factorial(n–1)
fact_cached = make_cached(factorial)
print(fact_cached(10)) # 计算
print(fact_cached(10)) # 缓存
案例6:循环闭包陷阱及解决
"""
loop_closure_trap.py
演示循环中创建闭包的经典问题及解决方案
"""
print("=== 错误示例 ===")
funcs = []
for i in range(3):
def f():
return i # 引用循环变量i
funcs.append(f)
for f in funcs:
print(f()) # 都输出2,因为所有f共享同一个i,循环结束后i=2
print("\\n=== 解决方案1:默认参数绑定当前值 ===")
funcs2 = []
for i in range(3):
def f(i=i): # 默认参数在定义时绑定当前i的值
return i
funcs2.append(f)
for f in funcs2:
print(f()) # 0 1 2
print("\\n=== 解决方案2:使用外层函数创建闭包(工厂函数) ===")
def create_func(x):
def f():
return x
return f
funcs3 = [create_func(i) for i in range(3)]
for f in funcs3:
print(f()) # 0 1 2
print("\\n=== 解决方案3:使用functools.partial ===")
from functools import partial
funcs4 = [partial(lambda x: x, i) for i in range(3)]
for f in funcs4:
print(f()) # 0 1 2
案例7:实际工作场景——配置管理
"""
config_closure.py
使用闭包管理配置信息
"""
def make_config(initial_config=None):
"""返回一个配置管理闭包,可以获取、设置、更新配置"""
config = initial_config.copy() if initial_config else {}
def get(key=None):
if key is None:
return config.copy() # 返回副本避免外部修改
return config.get(key)
def set(key, value):
config[key] = value
def update(new_config):
config.update(new_config)
return {"get": get, "set": set, "update": update}
# 创建配置实例
app_config = make_config({"debug": False, "host": "localhost"})
print(app_config["get"]()) # {'debug': False, 'host': 'localhost'}
app_config["set"]("debug", True)
print(app_config["get"]("debug")) # True
app_config["update"]({"port": 8080})
print(app_config["get"]()) # {'debug': True, 'host': 'localhost', 'port': 8080}
# 另一个独立的配置
db_config = make_config({"user": "admin", "password": "123"})
print(db_config["get"]("user")) # admin
# app_config不受影响
print(app_config["get"]("user")) # None
⚠️ 易错点避坑总结
| 1 | 函数内直接给全局变量赋值,以为会修改全局变量 | 创建了局部变量,全局未变 | 使用global声明 |
| 2 | 在嵌套函数内修改外层变量时忘记nonlocal | 创建了新的局部变量 | 使用nonlocal声明 |
| 3 | 循环中创建闭包引用循环变量 | 所有闭包共享同一个变量,结果不符合预期 | 用默认参数绑定当前值,或使用工厂函数 |
| 4 | 混淆global和nonlocal | 语法错误或逻辑错误 | 记住:全局用global,嵌套用nonlocal |
| 5 | 在函数内部使用与内置函数同名的变量 | 覆盖内置函数,导致后续调用失败 | 避免使用len、list等作为变量名 |
| 6 | 尝试在函数内部修改全局的可变对象(如列表)时,以为需要global | 实际上修改列表内容不需要global | 区分“重新赋值”和“修改对象内容” |
| 7 | 闭包中引用的变量是不可变类型,却直接赋值 | 创建了新的局部变量,未修改外层 | 使用nonlocal,或使用可变容器(列表) |
| 8 | 过度使用全局变量 | 代码耦合高,难以调试 | 尽量使用参数传递和返回值 |
| 9 | 不理解LEGB,在嵌套函数中误用了外层变量 | 变量查找错误 | 记住查找顺序,必要时使用print(locals())调试 |
| 10 | 闭包返回后,以为外层变量会被销毁 | 实际上闭包保留了引用,变量仍然存在 | 理解闭包的内存机制 |
📝 课后实战练习题
第1题:全局与局部变量分析
阅读以下代码,写出输出结果,并解释原因。
a = 10
def func():
print(a)
a = 20
print(a)
func()
print(a)
(提示:这会产生UnboundLocalError,解释为什么)
第2题:正确使用global
修改上面的代码,使其能正确输出:10(第一次打印全局)、20(局部修改)、20(全局修改)。使用global关键字。
第3题:嵌套函数与nonlocal
编写一个函数outer(),内部定义count = 0,再定义一个inner()函数,调用inner()可以使count增加1并打印。要求inner作为返回值,并在外部调用两次,观察输出。
第4题:闭包实现简单的平均值计算器
创建一个闭包make_averager(),它返回一个函数,该函数接收一个数值,并返回到目前为止所有传入数值的平均值。例如:
avg = make_averager()
print(avg(10)) # 10.0
print(avg(20)) # 15.0
print(avg(30)) # 20.0
提示:使用列表或nonlocal保存历史数据。
第5题:循环闭包陷阱修复
给定以下代码,预期输出0, 1, 2, 3, 4,但实际输出4,4,4,4,4。请用三种方法修复它。
functions = []
for i in range(5):
def f():
return i
functions.append(f)
for f in functions:
print(f())
第6题:LEGB查找顺序验证
在不运行代码的情况下,写出以下程序的输出,并说明每一步的查找过程。
x = "global"
def outer():
x = "outer"
def inner():
x = "inner"
print(x)
inner()
outer()
再修改:删除inner内的x = "inner",输出是什么?再删除outer内的x = "outer",输出是什么?
第7题:综合应用——带重置功能的计数器
编写一个闭包函数create_counter(start=0, step=1),返回三个函数:next()返回下一个值,reset()重置到起始值,set_step(new_step)修改步长。要求多个计数器独立。示例:
c = create_counter(10, 2)
print(c["next"]()) # 10
print(c["next"]()) # 12
c["set_step"](3)
print(c["next"]()) # 15
c["reset"]()
print(c["next"]()) # 10
🧠 知识点思维导图总结
#mermaid-svg-Nti4jnnMOkA15CqX{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Nti4jnnMOkA15CqX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Nti4jnnMOkA15CqX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Nti4jnnMOkA15CqX .error-icon{fill:#552222;}#mermaid-svg-Nti4jnnMOkA15CqX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Nti4jnnMOkA15CqX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Nti4jnnMOkA15CqX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Nti4jnnMOkA15CqX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Nti4jnnMOkA15CqX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Nti4jnnMOkA15CqX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Nti4jnnMOkA15CqX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Nti4jnnMOkA15CqX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Nti4jnnMOkA15CqX .marker.cross{stroke:#333333;}#mermaid-svg-Nti4jnnMOkA15CqX svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Nti4jnnMOkA15CqX p{margin:0;}#mermaid-svg-Nti4jnnMOkA15CqX .edge{stroke-width:3;}#mermaid-svg-Nti4jnnMOkA15CqX .section–1 rect,#mermaid-svg-Nti4jnnMOkA15CqX .section–1 path,#mermaid-svg-Nti4jnnMOkA15CqX .section–1 circle,#mermaid-svg-Nti4jnnMOkA15CqX .section–1 polygon,#mermaid-svg-Nti4jnnMOkA15CqX .section–1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .section–1 text{fill:#ffffff;}#mermaid-svg-Nti4jnnMOkA15CqX .node-icon–1{font-size:40px;color:#ffffff;}#mermaid-svg-Nti4jnnMOkA15CqX .section-edge–1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .edge-depth–1{stroke-width:17;}#mermaid-svg-Nti4jnnMOkA15CqX .section–1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled,#mermaid-svg-Nti4jnnMOkA15CqX .disabled circle,#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:lightgray;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:#efefef;}#mermaid-svg-Nti4jnnMOkA15CqX .section-0 rect,#mermaid-svg-Nti4jnnMOkA15CqX .section-0 path,#mermaid-svg-Nti4jnnMOkA15CqX .section-0 circle,#mermaid-svg-Nti4jnnMOkA15CqX .section-0 polygon,#mermaid-svg-Nti4jnnMOkA15CqX .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-Nti4jnnMOkA15CqX .section-0 text{fill:black;}#mermaid-svg-Nti4jnnMOkA15CqX .node-icon-0{font-size:40px;color:black;}#mermaid-svg-Nti4jnnMOkA15CqX .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-Nti4jnnMOkA15CqX .edge-depth-0{stroke-width:14;}#mermaid-svg-Nti4jnnMOkA15CqX .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled,#mermaid-svg-Nti4jnnMOkA15CqX .disabled circle,#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:lightgray;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:#efefef;}#mermaid-svg-Nti4jnnMOkA15CqX .section-1 rect,#mermaid-svg-Nti4jnnMOkA15CqX .section-1 path,#mermaid-svg-Nti4jnnMOkA15CqX .section-1 circle,#mermaid-svg-Nti4jnnMOkA15CqX .section-1 polygon,#mermaid-svg-Nti4jnnMOkA15CqX .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .section-1 text{fill:black;}#mermaid-svg-Nti4jnnMOkA15CqX .node-icon-1{font-size:40px;color:black;}#mermaid-svg-Nti4jnnMOkA15CqX .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .edge-depth-1{stroke-width:11;}#mermaid-svg-Nti4jnnMOkA15CqX .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled,#mermaid-svg-Nti4jnnMOkA15CqX .disabled circle,#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:lightgray;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:#efefef;}#mermaid-svg-Nti4jnnMOkA15CqX .section-2 rect,#mermaid-svg-Nti4jnnMOkA15CqX .section-2 path,#mermaid-svg-Nti4jnnMOkA15CqX .section-2 circle,#mermaid-svg-Nti4jnnMOkA15CqX .section-2 polygon,#mermaid-svg-Nti4jnnMOkA15CqX .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .section-2 text{fill:#ffffff;}#mermaid-svg-Nti4jnnMOkA15CqX .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-Nti4jnnMOkA15CqX .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .edge-depth-2{stroke-width:8;}#mermaid-svg-Nti4jnnMOkA15CqX .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled,#mermaid-svg-Nti4jnnMOkA15CqX .disabled circle,#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:lightgray;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:#efefef;}#mermaid-svg-Nti4jnnMOkA15CqX .section-3 rect,#mermaid-svg-Nti4jnnMOkA15CqX .section-3 path,#mermaid-svg-Nti4jnnMOkA15CqX .section-3 circle,#mermaid-svg-Nti4jnnMOkA15CqX .section-3 polygon,#mermaid-svg-Nti4jnnMOkA15CqX .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .section-3 text{fill:black;}#mermaid-svg-Nti4jnnMOkA15CqX .node-icon-3{font-size:40px;color:black;}#mermaid-svg-Nti4jnnMOkA15CqX .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .edge-depth-3{stroke-width:5;}#mermaid-svg-Nti4jnnMOkA15CqX .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled,#mermaid-svg-Nti4jnnMOkA15CqX .disabled circle,#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:lightgray;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:#efefef;}#mermaid-svg-Nti4jnnMOkA15CqX .section-4 rect,#mermaid-svg-Nti4jnnMOkA15CqX .section-4 path,#mermaid-svg-Nti4jnnMOkA15CqX .section-4 circle,#mermaid-svg-Nti4jnnMOkA15CqX .section-4 polygon,#mermaid-svg-Nti4jnnMOkA15CqX .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .section-4 text{fill:black;}#mermaid-svg-Nti4jnnMOkA15CqX .node-icon-4{font-size:40px;color:black;}#mermaid-svg-Nti4jnnMOkA15CqX .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .edge-depth-4{stroke-width:2;}#mermaid-svg-Nti4jnnMOkA15CqX .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled,#mermaid-svg-Nti4jnnMOkA15CqX .disabled circle,#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:lightgray;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:#efefef;}#mermaid-svg-Nti4jnnMOkA15CqX .section-5 rect,#mermaid-svg-Nti4jnnMOkA15CqX .section-5 path,#mermaid-svg-Nti4jnnMOkA15CqX .section-5 circle,#mermaid-svg-Nti4jnnMOkA15CqX .section-5 polygon,#mermaid-svg-Nti4jnnMOkA15CqX .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .section-5 text{fill:black;}#mermaid-svg-Nti4jnnMOkA15CqX .node-icon-5{font-size:40px;color:black;}#mermaid-svg-Nti4jnnMOkA15CqX .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .edge-depth-5{stroke-width:-1;}#mermaid-svg-Nti4jnnMOkA15CqX .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled,#mermaid-svg-Nti4jnnMOkA15CqX .disabled circle,#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:lightgray;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:#efefef;}#mermaid-svg-Nti4jnnMOkA15CqX .section-6 rect,#mermaid-svg-Nti4jnnMOkA15CqX .section-6 path,#mermaid-svg-Nti4jnnMOkA15CqX .section-6 circle,#mermaid-svg-Nti4jnnMOkA15CqX .section-6 polygon,#mermaid-svg-Nti4jnnMOkA15CqX .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .section-6 text{fill:black;}#mermaid-svg-Nti4jnnMOkA15CqX .node-icon-6{font-size:40px;color:black;}#mermaid-svg-Nti4jnnMOkA15CqX .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .edge-depth-6{stroke-width:-4;}#mermaid-svg-Nti4jnnMOkA15CqX .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled,#mermaid-svg-Nti4jnnMOkA15CqX .disabled circle,#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:lightgray;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:#efefef;}#mermaid-svg-Nti4jnnMOkA15CqX .section-7 rect,#mermaid-svg-Nti4jnnMOkA15CqX .section-7 path,#mermaid-svg-Nti4jnnMOkA15CqX .section-7 circle,#mermaid-svg-Nti4jnnMOkA15CqX .section-7 polygon,#mermaid-svg-Nti4jnnMOkA15CqX .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .section-7 text{fill:black;}#mermaid-svg-Nti4jnnMOkA15CqX .node-icon-7{font-size:40px;color:black;}#mermaid-svg-Nti4jnnMOkA15CqX .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .edge-depth-7{stroke-width:-7;}#mermaid-svg-Nti4jnnMOkA15CqX .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled,#mermaid-svg-Nti4jnnMOkA15CqX .disabled circle,#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:lightgray;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:#efefef;}#mermaid-svg-Nti4jnnMOkA15CqX .section-8 rect,#mermaid-svg-Nti4jnnMOkA15CqX .section-8 path,#mermaid-svg-Nti4jnnMOkA15CqX .section-8 circle,#mermaid-svg-Nti4jnnMOkA15CqX .section-8 polygon,#mermaid-svg-Nti4jnnMOkA15CqX .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .section-8 text{fill:black;}#mermaid-svg-Nti4jnnMOkA15CqX .node-icon-8{font-size:40px;color:black;}#mermaid-svg-Nti4jnnMOkA15CqX .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .edge-depth-8{stroke-width:-10;}#mermaid-svg-Nti4jnnMOkA15CqX .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled,#mermaid-svg-Nti4jnnMOkA15CqX .disabled circle,#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:lightgray;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:#efefef;}#mermaid-svg-Nti4jnnMOkA15CqX .section-9 rect,#mermaid-svg-Nti4jnnMOkA15CqX .section-9 path,#mermaid-svg-Nti4jnnMOkA15CqX .section-9 circle,#mermaid-svg-Nti4jnnMOkA15CqX .section-9 polygon,#mermaid-svg-Nti4jnnMOkA15CqX .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .section-9 text{fill:black;}#mermaid-svg-Nti4jnnMOkA15CqX .node-icon-9{font-size:40px;color:black;}#mermaid-svg-Nti4jnnMOkA15CqX .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .edge-depth-9{stroke-width:-13;}#mermaid-svg-Nti4jnnMOkA15CqX .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled,#mermaid-svg-Nti4jnnMOkA15CqX .disabled circle,#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:lightgray;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:#efefef;}#mermaid-svg-Nti4jnnMOkA15CqX .section-10 rect,#mermaid-svg-Nti4jnnMOkA15CqX .section-10 path,#mermaid-svg-Nti4jnnMOkA15CqX .section-10 circle,#mermaid-svg-Nti4jnnMOkA15CqX .section-10 polygon,#mermaid-svg-Nti4jnnMOkA15CqX .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .section-10 text{fill:black;}#mermaid-svg-Nti4jnnMOkA15CqX .node-icon-10{font-size:40px;color:black;}#mermaid-svg-Nti4jnnMOkA15CqX .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .edge-depth-10{stroke-width:-16;}#mermaid-svg-Nti4jnnMOkA15CqX .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled,#mermaid-svg-Nti4jnnMOkA15CqX .disabled circle,#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:lightgray;}#mermaid-svg-Nti4jnnMOkA15CqX .disabled text{fill:#efefef;}#mermaid-svg-Nti4jnnMOkA15CqX .section-root rect,#mermaid-svg-Nti4jnnMOkA15CqX .section-root path,#mermaid-svg-Nti4jnnMOkA15CqX .section-root circle,#mermaid-svg-Nti4jnnMOkA15CqX .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-Nti4jnnMOkA15CqX .section-root text{fill:#ffffff;}#mermaid-svg-Nti4jnnMOkA15CqX .section-root span{color:#ffffff;}#mermaid-svg-Nti4jnnMOkA15CqX .section-2 span{color:#ffffff;}#mermaid-svg-Nti4jnnMOkA15CqX .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-Nti4jnnMOkA15CqX .edge{fill:none;}#mermaid-svg-Nti4jnnMOkA15CqX .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-Nti4jnnMOkA15CqX :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
第13课:作用域与闭包
作用域分类
局部作用域 Local
嵌套作用域 Enclosing
全局作用域 Global
内置作用域 Built-in
LEGB规则
查找顺序
屏蔽效应
global关键字
修改全局变量
常量定义
nonlocal关键字
修改外层嵌套变量
与global的区别
闭包Closure
形成条件
嵌套函数
引用外层变量
返回内层函数
作用
数据隐藏
代替小类
装饰器基础
常见陷阱
循环中创建闭包
可变对象vs不可变
面试考点
LEGB顺序
global vs nonlocal
闭包定义与用途
循环闭包解决方案
🔜 下节课预告
闭包是一个函数“记住”了外层变量的值。如果我们将函数作为参数传递或作为返回值,就引出了高阶函数的概念。下一节课我们将学习Python中的高阶函数、lambda表达式以及内置的高阶函数map、filter、sorted。
第14课:高阶函数、lambda匿名函数、map/filter/sorted内置高阶函数实战
内容包括:
- Lambda匿名函数的语法与使用场景
- 高阶函数的概念
- map:对可迭代对象每个元素应用函数
- filter:过滤可迭代对象元素
- sorted:灵活排序(key参数)
- 结合lambda实现简洁的数据处理
- 实战:数据清洗、排序、转换
高阶函数是函数式编程的基石,掌握它能让你的代码更简洁、更Pythonic。
🌟 学习鼓励:作用域和闭包是Python进阶的第一个门槛。你可能需要多花一些时间理解nonlocal和闭包的内存行为。请务必亲手调试文中的案例,观察变量的id或__closure__属性,你一定会有豁然开朗的感觉。坚持就是胜利!
🔗《50节课 Python 从入门到精通》系列课程导航
去订阅
🌟 感谢您耐心阅读到这里! 💡 如果本文对您有所启发欢迎: 👍 点赞📌 收藏 📤 分享给更多需要的伙伴。 🗣️ 期待在评论区看到您的想法, 共同进步。 🔔 关注我,持续获取更多干货内容~ 🤗 我们下篇文章见~





