Files
python/20-24/16scope.py
T
2026-05-06 11:21:42 +08:00

138 lines
4.1 KiB
Python

# 变量的作用域(scope)指的是一个变量在程序中可以被访问的范围。Python中的变量作用域遵循LEGB规则,即按照以下顺序查找变量:
# L (Local):局部作用域
# E (Enclosing):嵌套作用域
# G (Global):全局作用域
# B (Built-in):内置作用域
# 基本特点
# 局部作用域:函数内部定义的变量,只能在函数内部访问
# 嵌套作用域:嵌套函数中外层函数的变量对内层函数可见
# 全局作用域:模块级别定义的变量,在整个模块中可见
# 内置作用域:Python内置的函数和变量
# 定义一个外层函数outer_function
def outer_function():
# 在外层函数中定义一个变量y,并赋值为20
y = 20
print(f"外层函数中的y: {y}")
# 在外层函数内部定义一个内层函数inner_function
def inner_function():
# 内层函数可以访问外层函数的变量y
print(f"内层函数访问外层变量y: {y}")
# 预期输出: 内层函数访问外层变量y: 20
# 调用内层函数
inner_function()
# 在外层函数中再次打印y
print(f"外层函数中y的值: {y}")
# 调用外层函数
outer_function()
# 全局作用域的修改
# 在嵌套作用域中,内层函数可以“读取”外层函数的变量,但如果要“直接修改”外层变量,会遇到限制。
# 默认情况下,如果你在内层函数中为某个变量赋值,这个变量会被视为“局部变量”,而不是外层的同名变量。这种行为可能会导致UnboundLocalError错误
def outer():
num = 10 # 外层变量
def inner():
# 尝试直接修改外层变量,会报错
try:
num += 1 # 内层函数会认为num是自己的局部变量
except UnboundLocalError as e:
print(f"错误: {e}")
inner()
print(f"最终num: {num}")
outer()
# 输出: 错误: local variable 'num' referenced before assignment
# 最终num: 10
# 在Python中,如果想在函数内部修改全局变量,必须用global关键字声明该变量属于全局作用域,否则Python会将其当作一个新的局部变量,导致修改的只是函数内部的“影子”变量,而不是外部真正的全局变量。
# 总结:
# 只读全局变量时可直接在函数内引用;
# 想在函数内修改全局变量值,必须加global关键字;
# 否则会创建/修改局部变量,不会影响全局作用域中的变量值。
global_var = 100
def modify_global():
global global_var
global_var += 10
print(f"函数内部修改后的global_var{global_var}") # 110
modify_global()
print(f"函数外部的global_var{global_var}") # 110
# nonlocal关键字的高级用法
# 在嵌套函数中修改外层嵌套函数的变量
print("----------nonlocal--------------------")
def complex_outer():
outer_var = "外层变量"
count = 0
def middle_function():
middle_var = "中层变量"
def inner_function():
nonlocal outer_var, count
outer_var = "被内层函数修改"
count += 1
print(f"内层函数修改外层变量: {outer_var}")
print(f"内层函数修改计数器: {count}")
inner_function()
print(f"中层函数检查中层变量: {middle_var}")
middle_function()
print(f"外层函数检查外层变量: {outer_var}")
print(f"外层函数检查计数器: {count}")
complex_outer()
# 定义一个全局变量
conflict_var = "全局变量"
print(f"初始全局变量: {conflict_var}")
# 定义一个函数来演示变量名冲突
# 这是一个作用域冲突导致的语法错误。
# 解决方案 将 global 声明放在函数开头(推荐)
# def conflict_demo():
# # 在函数内部定义同名变量
# conflict_var = "局部变量"
# print(f"函数内部局部变量: {conflict_var}")
# # 如果要访问全局变量,需要使用global关键字
# global conflict_var
# print(f"使用global后的全局变量: {conflict_var}")
# # 调用函数
# conflict_demo()
# # 检查全局变量
# print(f"函数外部全局变量: {conflict_var}")