如何在discord.py中通过自定义装饰器向命令注入参数?
解决discord.py自定义装饰器传递game对象并避免参数缺失错误
问题出在自定义装饰器没有正确保留原命令函数的签名,discord.py需要通过函数签名识别必填参数(比如ctx),仅设置__name__不足以让框架正确解析参数。另外,装饰器的wrapper需要兼容命令可能带的额外参数,保证逻辑复用性。
正确的装饰器实现
首先导入functools来保留函数签名:
import functools from discord.ext import commands from your_module import GameState # 替换为你的GameState实际导入路径 def is_game_running(func): @functools.wraps(func) async def wrapper(self, ctx, *args, **kwargs): # 获取并检查当前频道的游戏状态 game = self.game_manager.get_game(ctx.channel.id) if not game or game.state == GameState.FINISHED: return # 将验证通过的game对象传递给原命令函数 return await func(self, ctx, game, *args, **kwargs) return wrapper
命令函数的使用方式
在类中的命令上应用装饰器,直接接收传递过来的game对象:
class GameCog(commands.Cog): def __init__(self, bot): self.bot = bot self.game_manager = ... # 初始化你的游戏管理器实例 @commands.command() @is_game_running async def example_command(self, ctx, game): # 直接使用game对象编写业务逻辑 await ctx.send(f"当前游戏状态:{game.state}")
原理说明
@functools.wraps(func)会把原函数的元数据(参数签名、文档字符串等)复制到wrapper函数中,让discord.py能正确识别ctx这类必填参数,彻底解决MissingRequiredArgument错误。*args和**kwargs用于兼容带额外用户输入参数的命令,确保装饰器能复用在不同参数结构的命令上。- 装饰器完成游戏状态检查后,自动将
game对象传递给原命令函数,完全消除了重复的检查代码。
内容的提问来源于stack exchange,提问作者Kasper
相关产品推荐
相关产品推荐

