You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python全局与函数作用域问题:为何读取全局变量无错赋值报错

Python作用域规则解释

问题代码

def take_damage():
  health -= 20  # UNDERSTANDABLE ERROR

def check_health():
  if (health <= 0):   # WHY NO ERROR HERE, TOO?
    print("You have died!")
    quit()
  else:
    print("Your health is "+ str(health)) # HOW DOES IT WORK HERE?
     
  
health = 100
take_damage()
check_health()

核心规则说明

你观察到的差异本质是Python对函数内部变量的读取操作和赋值操作的判定逻辑完全不同:

  • 只要函数内部出现了对某个变量的赋值行为(包括=、+=、-=等所有写操作),Python在编译函数阶段就会将这个变量标记为局部作用域变量,运行时只会在函数局部查找该变量,找不到就抛出UnboundLocalError。
    对应take_damage函数的逻辑:health -= 20属于隐式赋值,所以Python将health判定为局部变量,但执行减操作前局部作用域没有定义过health,因此报错,这和你已知的结论一致。
  • 如果函数内部只有对某个变量的读取操作,没有任何赋值操作,Python不会将其标记为局部变量,运行时会按照LEGB顺序逐层向上查找变量:
    • L(Local):当前函数的局部作用域
    • E(Enclosed):外层嵌套函数的闭包作用域
    • G(Global):当前模块的全局作用域
    • B(Built-in):Python内置作用域
      只要在任意一层找到对应变量就直接使用,找不到才会抛出NameError。
      对应check_health函数的逻辑:整个函数内只有对health的读取判断、类型转换操作,没有赋值行为,因此Python会逐层向上查找,最终找到全局定义的health = 100,完全符合运行规则,不会报错。

补充说明

如果需要在函数内部修改全局变量,必须显式添加global 变量名声明,告知Python该变量不需要判定为局部变量,直接使用全局作用域的对应变量即可。

内容的提问来源于stack exchange,提问作者dadiletta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 05:48:03