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

discord.py中self未定义报错,如何实现下拉菜单选分类显示命令文档字符串?

问题

我需要实现一个功能:通过Discord机器人的下拉菜单选择命令分类,展示该分类下所有命令的文档字符串。但运行代码时触发“self未定义”错误,代码如下:

class OptionView(discord.ui.View):
    @discord.ui.select(placeholder = "Option", min_values=1, max_values=1, options=[
            discord.SelectOption(label=filename[:-3]) for filename in self.bot.get_cog()
        ])
    
    async def select_callback(self, interaction:discord.Interaction,select:discord.ui.Select):
            embed = discord.Embed(
                title='Commands',
                colour=discord.Color.blue()
            )

            self.disabled = True
            value = select.values[0] # command's category
            
            commands_list = [command.name for command in self.bot.get_cog(value).get_commands()]  # Get command names in the category

            for command in commands_list:
                cmd = self.bot.get_command(command)
                docstring = cmd.callback.__doc__ or "No docstring"
                embed.add_field(name=command, value=docstring, inline=True)
                await interaction.response.send_message(embed=embed)
                
            await interaction.response.send_message(embed=embed,view=OptionView())
错误原因与修复方案

核心错误原因

装饰器@discord.ui.select是在类定义阶段执行的,此时类还没有被实例化,self这个实例对象根本不存在,所以在装饰器的options参数里直接用self.bot.get_cog()会触发“self未定义”错误。

修复步骤

  1. 将下拉菜单的选项初始化移到类的__init__方法中,只有在实例化View时才能访问到self和bot实例。
  2. 给OptionView的构造方法添加bot参数,确保View能获取到机器人实例。
  3. 修正回调函数里的逻辑错误:
    • 循环内不要重复发送消息,应该先把所有字段添加到Embed后再统一发送。
    • 重新创建OptionView时要传入bot实例,否则新的View会缺少必要的机器人引用。
    • 若要禁用下拉菜单,应该设置select.disabled = True而非self.disabled = True(后者会禁用整个View)。

修正后的完整代码

class OptionView(discord.ui.View):
    def __init__(self, bot):
        super().__init__()
        self.bot = bot
        
        # 在__init__中初始化下拉菜单选项
        cog_names = [cog.__class__.__name__ for cog in self.bot.cogs.values()]
        select_options = [discord.SelectOption(label=name) for name in cog_names]
        
        # 创建下拉菜单组件并添加到View
        self.select_menu = discord.ui.Select(
            placeholder="选择命令分类",
            min_values=1,
            max_values=1,
            options=select_options
        )
        self.select_menu.callback = self.select_callback
        self.add_item(self.select_menu)

    async def select_callback(self, interaction: discord.Interaction, select: discord.ui.Select):
        embed = discord.Embed(
            title='命令列表',
            colour=discord.Color.blue()
        )

        # 禁用当前下拉菜单
        select.disabled = True
        value = select.values[0]  # 获取选中的分类名称
        
        # 获取该分类下的所有命令
        cog = self.bot.get_cog(value)
        if not cog:
            await interaction.response.send_message("该分类不存在", ephemeral=True)
            return
        
        commands_list = cog.get_commands()
        for command in commands_list:
            docstring = command.callback.__doc__ or "无文档说明"
            embed.add_field(name=command.name, value=docstring, inline=True)
        
        # 发送Embed并更新View(禁用后的菜单)
        await interaction.response.send_message(embed=embed, view=self)

关键修改说明

  • 把下拉菜单的创建逻辑移到__init__,确保实例化时才能访问self.bot,避免类定义阶段的self未定义问题。
  • 直接通过self.bot.cogs.values()获取所有Cog实例,再提取名称,比原代码的get_cog()调用更准确(原代码get_cog()需要传入名称,这里应该是获取所有Cog的名称)。
  • 修复了回调中重复发送消息的问题,改为统一发送完整的Embed。
  • 增加了Cog不存在的判断,避免空引用错误。
  • 禁用下拉菜单后直接使用当前View回复,不需要重新创建新的View实例(如果需要重新启用可以另行处理)。

内容的提问来源于stack exchange,提问作者克克KeJC

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 10:58:14