# 变量的作用域(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}")