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
相关产品推荐
相关产品推荐

