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

Python3函数内全局变量tokens报错:引用前未定义问题排查求助

报错原因

Python存在作用域查找规则,当你在函数内部对某个变量执行赋值类操作(包括+=、-=、直接赋值等)时,Python解释器会默认将该变量标记为函数内部的局部变量,不会再去外层作用域查找对应的变量。
你代码中的tokens是定义在全局作用域的变量,函数内的tokens += amount本质等价于tokens = tokens + amount,属于赋值操作,因此Python会将tokens识别为当前函数的局部变量,但你在读取赋值符号右侧的tokens时,局部作用域内还没有对该变量的定义,因此触发了“引用前未赋值”的报错。

另外你的代码还存在两处额外可修复的问题:

  • randint(1, 0)参数顺序错误,random.randint要求第一个参数小于等于第二个参数,需改为randint(0, 1)才能正常生成0或1的随机数
  • input("double? ").lower漏了括号,lower是字符串方法,需要调用lower()才能得到小写的输入结果,否则你对比的是方法对象和字符串,永远返回False
解决方法

这里提供三种常见的修复方案:

方案1:添加global声明(快速修复)

在函数开头添加global tokens声明,明确告诉Python该变量使用全局作用域的定义,不要识别为局部变量。
修复后的代码示例:

from random import randint
tokens = 100

def double_or_nothing(amount):
    global tokens
    if randint(0, 1) == 1:
        if input("double? ").lower() == "yes":
            amount *= 2
            double_or_nothing(amount)
        else:
            tokens += amount
    else:
        tokens -= amount

方案2:用可变对象封装状态(避免global关键字)

可以将全局变量封装为可变对象(比如列表、字典),你修改的是可变对象内部的元素,而非对变量本身执行赋值操作,因此不会触发局部变量的识别逻辑:

from random import randint
tokens = [100] # 用列表封装,列表是可变对象

def double_or_nothing(amount):
    if randint(0, 1) == 1:
        if input("double? ").lower() == "yes":
            amount *= 2
            double_or_nothing(amount)
        else:
            tokens[0] += amount
    else:
        tokens[0] -= amount

方案3:取消全局变量,用参数传递和返回值处理状态(最推荐)

全局变量容易产生不可预知的副作用,更合理的写法是将状态作为参数传入函数,执行完成后返回新的状态,由外层代码更新:

from random import randint

def double_or_nothing(amount, tokens):
    if randint(0, 1) == 1:
        if input("double? ").lower() == "yes":
            return double_or_nothing(amount * 2, tokens)
        else:
            return tokens + amount
    else:
        return tokens - amount

# 调用示例
tokens = 100
tokens = double_or_nothing(10, tokens)
print(tokens)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 08:27:05