如何在discord.py中用类内对象方法实现斜杠命令类内装饰?
解决discord.py类内整合CommandTree与斜杠命令的错误
问题背景
通过视频教程实现的Discord斜杠命令代码可正常运行,但希望将外部的CommandTree实例化、斜杠命令装饰逻辑整合到自定义aClient类内部,尝试的代码触发如下错误:
Traceback (most recent call last): File "E:\myprojects\new.py", line 33, in <module> client = aClient() File "E:\myprojects\new.py", line 15, in __init__ self.slash = self.tree.command(self.tree, name="name", description="name", guild=discord.Object(id=GUILD_ID)) TypeError: CommandTree.command() takes 1 positional argument but 2 positional arguments (and 3 keyword-only arguments) were given
错误原因
- 多余参数传递:
self.tree.command()是装饰器方法,无需手动传入self.tree作为第一个参数,装饰器会自动处理被装饰的函数。 - 同名属性冲突:在
__init__中给self.slash赋值装饰器后,又在类内定义同名的async def slash()方法,导致后者覆盖前者,破坏装饰器逻辑。 - 异步方法未await:
self.tree.sync()是异步方法,代码中未添加await关键字,会触发运行时错误。
正确实现方式
以下提供两种可行的类内整合方案,均已适配环境变量存储GUILD_ID和TOKEN的场景:
方案1:在__init__中注册命令方法
直接将类内定义的命令方法注册到CommandTree,逻辑清晰直观:
import discord from discord import app_commands import os class aClient(discord.Client): def __init__(self): # 根据需求设置Intents,此处使用默认权限 super().__init__(intents=discord.Intents.default()) self.tree = app_commands.CommandTree(self) self.synced = False # 将类内的命令方法注册到CommandTree guild_id = discord.Object(id=int(os.getenv("GUILD_ID"))) self.tree.command(name="test", description="testing", guild=guild_id)(self.slash_test) async def on_ready(self): await self.wait_until_ready() if not self.synced: guild_id = discord.Object(id=int(os.getenv("GUILD_ID"))) await self.tree.sync(guild=guild_id) self.synced = True print(f"Logged in as {self.user}") async def slash_test(self, interaction: discord.Interaction, name: str): await interaction.response.send_message(f"Hello {name}!") client = aClient() client.run(os.getenv("TOKEN"))
方案2:使用类属性封装装饰器
通过@property将self.tree.command封装为类装饰器,保持装饰器的使用习惯:
import discord from discord import app_commands import os class aClient(discord.Client): def __init__(self): super().__init__(intents=discord.Intents.default()) self.tree = app_commands.CommandTree(self) self.synced = False self.guild_id = discord.Object(id=int(os.getenv("GUILD_ID"))) async def on_ready(self): await self.wait_until_ready() if not self.synced: await self.tree.sync(guild=self.guild_id) self.synced = True print(f"Logged in as {self.user}") # 封装CommandTree的command装饰器为类属性 @property def command(self): return self.tree.command # 使用自定义的类装饰器注册斜杠命令 @command(name="test", description="testing", guild=lambda self: self.guild_id) async def slash_test(self, interaction: discord.Interaction, name: str): await interaction.response.send_message(f"Hello {name}!") client = aClient() client.run(os.getenv("TOKEN"))
关键注意事项
- 确保
GUILD_ID从环境变量读取后转换为int类型,因为Discord的服务器ID是整数。 - 所有异步方法(如
on_ready内的self.tree.sync())必须添加await关键字。 - Intents权限需根据实际功能需求配置,避免因权限不足导致命令无法响应。
内容的提问来源于stack exchange,提问作者Ajaykrishnan R
相关产品推荐
相关产品推荐

