You need to enable JavaScript to run this app. discord.py 如何仅在布尔值为真时运行命令及解决UnboundLocalError
优惠活动
大模型
产品
解决方案
定价
更多

discord.py 如何仅在布尔值为真时运行命令及解决UnboundLocalError

代码报错修复与单次作答逻辑实现

报错核心成因

  • Python作用域规则判定:只要函数内部存在对某个变量的赋值语句,该变量会被自动识别为函数局部变量。你在ans函数中写了ongt = False的赋值代码,却在赋值前用if not ongt:读取变量值,直接触发「局部变量赋值前被引用」的UnboundLocalError。
  • 全局作用域从未初始化ongt、user、be、chosen_trivia这些零散变量,就算没有作用域判定问题,第一次执行>ans命令时也会因变量不存在直接报错。
  • 零散全局变量的设计本身存在缺陷:仅能支持单轮单人的问答流程,多用户同时触发问答时全局状态会被直接覆盖,也无法精准实现「单题仅允许提交一次答案」的限制。

代码附带的隐性逻辑Bug

  • 自定义的random_trivia函数只写了随机选题逻辑,没有配置返回语句,调用后会返回空值。
  • 代码中调用的random_tri()无对应函数定义,且未导入random模块。
  • 读取economy[ctx.author]时,如果用户没有对应资产记录,会直接触发KeyError。
  • 答错提示中取答案的逻辑引用了不存在的random_tri方法,会随机匹配无关的题库答案,和当前题目不对应。

修复后可实现单次作答的参考代码

import discord
import random
from discord.ext import commands

trivia_list = {
    "Capital of Spain?": "madrid",
    "Capital of India?": "delhi",
    "Language with the most words?": "english",
    "What is the hardest rock?": "diamond",
    "Planet with the most gravity?": "jupiter",
    "What year was the first iPhone released?": "2007",
    "What does DC stand for (the comics)?": "detective comics",
    "What country won the very first FIFA World Cup in 1930?": "uruguay",
    "What is the body's largest organ?": "skin"
}

economy = {}
# 用独立会话字典存储问答状态,从机制上避免全局状态混乱
active_trivia = {}

client = commands.Bot(command_prefix=">")

@client.command()
async def trivia(ctx, bet_amount: int):
    # 已有未完成问答的用户无法开启新对局
    if ctx.author.id in active_trivia:
        await ctx.send("你当前有未完成的问答,无法开启新对局")
        return
    # 校验下注金额是否超出用户持有金币
    user_coins = economy.get(ctx.author.id, 0)
    if bet_amount > user_coins:
        await ctx.send(f"下注失败,你当前持有{user_coins}金币,无法下注{bet_amount}")
        return
    # 随机抽选题库题目
    question, correct_ans = random.choice(list(trivia_list.items()))
    # 保存当前用户的问答会话
    active_trivia[ctx.author.id] = {
        "question": question,
        "correct_ans": correct_ans,
        "bet": bet_amount,
        "is_submitted": False
    }
    await ctx.send(f"新问答开启:{question}")

@client.command()
async def ans(ctx, answer):
    # 无有效问答会话的用户无法作答
    user_session = active_trivia.get(ctx.author.id)
    if not user_session:
        await ctx.send("当前没有你可以作答的问答")
        return
    # 已提交过答案的用户直接拦截,实现单次作答限制
    if user_session["is_submitted"]:
        await ctx.send("你已经提交过本题的答案,无法重复作答")
        return
    # 标记为已提交,不管后续答对答错都不允许再次提交
    user_session["is_submitted"] = True
    normalized_ans = answer.lower().strip()
    if normalized_ans == user_session["correct_ans"]:
        # 答对结算金币
        economy[ctx.author.id] = economy.get(ctx.author.id, 0) + user_session["bet"]
        await ctx.send(f"回答正确!你获得{user_session['bet']}金币,当前账户共有{economy[ctx.author.id]}金币")
    else:
        # 答错扣除对应下注金币
        economy[ctx.author.id] = economy.get(ctx.author.id, 0) - user_session["bet"]
        await ctx.send(f"回答错误,正确答案为{user_session['correct_ans']},当前账户共有{economy[ctx.author.id]}金币")
    # 作答完成后清理会话状态
    del active_trivia[ctx.author.id]

上述修复代码从机制上实现了单题单次作答限制:用户提交第一次答案后,会话会被标记为已提交状态,后续重复调用>ans命令会被直接拦截,同时解决了原代码中的未绑定变量、KeyError、状态串线等问题,支持多用户同时触发问答互不干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 05:57:01