一、开场白
在Python的世界里,变量并非随处可见、随手可用——就像我们生活中不同的空间有不同的“使用规则”:家里的钥匙只能开自家的门,公司的权限只适用于办公区域,公共区域的资源人人可享。变量的“可用范围”,就是Python中核心的作用域概念,而LEGB规则正是解开这层“使用规则”的钥匙。它藏在每一行代码的执行逻辑里,决定了程序如何找到你定义的变量、函数,甚至能避免很多新手踩坑的“变量找不到”“值不对”的问题,理解它,才算真正走进Python变量管理的核心。
二、Python作用域(LEGB规则)概念与例子
Python的作用域遵循LEGB规则,本质是变量查找的优先级顺序,四个字母分别对应四种作用域,优先级从高到低依次为:
- L(Local)局部作用域:函数、类方法、循环/条件语句等代码块内部定义的变量,仅在该代码块内生效;
- E(Enclosing)嵌套作用域:嵌套函数中,外层函数的作用域(非全局),内层函数可访问外层函数的变量,但外层无法访问内层;
- G(Global)全局作用域:在整个.py文件(模块)顶层定义的变量,整个模块内均可访问;
- B(Built-in)内置作用域:Python自带的内置函数/变量(如print、len、int),无需定义即可全局使用。
3个直观例子帮你理解:
例子1:局部作用域(L)
defcalculate():
# 局部变量,仅在calculate函数内有效
num = 10
print(num) # 输出:10
calculate()
# print(num) # 报错:NameError: name 'num' is not defined(局部变量外部不可访问)
例子2:嵌套作用域(E)
defouter():
# 外层函数变量,属于嵌套作用域
outer_num = 20
definner():
# 内层函数可访问外层的嵌套作用域变量
print(outer_num) # 输出:20
inner()
outer()
# print(outer_num) # 报错:NameError: name 'outer_num' is not defined(外层变量全局不可访问)
例子3:全局+内置作用域(G+B)
# 全局变量,整个文件可访问
global_num = 30
defprint_info():
# 访问全局变量
print(global_num) # 输出:30
# 访问内置作用域的len函数(无需定义,Python自带)
print(len([1,2,3])) # 输出:3
print_info()
print(global_num) # 输出:30(全局变量外部可访问)
三、人性化的相关问题(附答案+过程)
问题1:为什么在函数里修改全局变量会报错?该怎么正确修改?
思考过程:Python默认在函数内赋值的变量是局部变量,若直接修改全局变量,解释器会认为你想定义新的局部变量,而非修改全局变量,因此报错。要修改全局变量,需用global关键字声明。答案:
global_num = 30
defmodify_global():
# 声明使用全局变量
global global_num
global_num = 40
modify_global()
print(global_num) # 输出:40(成功修改全局变量)
问题2:嵌套函数中,内层想修改外层嵌套作用域的变量,该怎么做?
思考过程:嵌套作用域的变量默认仅可读,若内层函数要修改,需用nonlocal关键字声明(区别于global,nonlocal针对嵌套作用域,global针对全局作用域)。答案:
defouter():
outer_num = 20
definner():
# 声明使用嵌套作用域的变量
nonlocal outer_num
outer_num = 25
inner()
print(outer_num) # 输出:25(成功修改嵌套作用域变量)
outer()
问题3:如果局部、嵌套、全局、内置作用域有同名变量,Python会优先用哪个?
思考过程:LEGB规则的核心是“优先级从高到低”,即先找局部(L),找不到再找嵌套(E),接着全局(G),最后内置(B)。答案:
# 内置作用域有len函数,这里全局定义同名len
len = 100# 全局作用域(G)
defouter():
len = 200# 嵌套作用域(E)
definner():
len = 300# 局部作用域(L)
print(len) # 优先用局部的300
inner()
outer() # 输出:300
四、全文汇总总结
核心知识点
- Python作用域遵循LEGB规则,是变量查找的优先级顺序:Local(局部)> Enclosing(嵌套)> Global(全局)> Built-in(内置);
- 局部作用域仅在代码块(函数/循环等)内生效,嵌套作用域针对嵌套函数的外层,全局作用域覆盖整个模块,内置作用域是Python自带的函数/变量;
- 修改全局变量需用
global关键字,修改嵌套作用域变量需用nonlocal关键字。
区别与联系
联系:四种作用域共同构成Python的变量查找体系,遵循“就近优先”的核心逻辑;局部/嵌套作用域是临时作用域(函数执行完即销毁),全局/内置作用域是持久作用域(模块运行期间/整个Python环境生效)。