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

如何在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 

错误原因

  1. 多余参数传递:self.tree.command()是装饰器方法,无需手动传入self.tree作为第一个参数,装饰器会自动处理被装饰的函数。
  2. 同名属性冲突:在__init__中给self.slash赋值装饰器后,又在类内定义同名的async def slash()方法,导致后者覆盖前者,破坏装饰器逻辑。
  3. 异步方法未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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 08:06:21