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

Discord.py中View类实例化时__init__赋值被按钮忽略的问题

问题描述

我尝试用Discord.Py创建标签可动态变化的按钮,为此写了一个discord.ui.View的子类,__init__方法接收name和id参数。实例化时断点显示self.modelName和self.modelId已经成功赋值,但生成的按钮完全忽略这些值,用的是类定义的默认值。

类定义代码:

class AlphaStrikeCardButtons(discord.ui.View):
    modelName = "supernova 2"
    modelId = "3133"

    #defining constructor  
    def __init__(self,name,id):  
        super().__init__()
        self.modelName = name
        self.modelId = f'asc{id}'
        
    @discord.ui.button(label=modelName, custom_id=modelId, style=discord.ButtonStyle.blurple)
    #@discord.ui.button(label='supernova 5', custom_id='asc8132', style=discord.ButtonStyle.blurple)
    async def alphaStrikeCard(self, interaction: discord.Interaction, button: discord.ui.Button):
        cardPath = f'./tmp/asc{modelId}.png' #If it already exists, we don't need to download it again
        if os.path.isfile(cardPath) == False:
            cardUrl = f'http://masterunitlist.info/Unit/Card/{self.modelId}'
            print(cardUrl)
            urlretrieve(cardUrl,cardPath)
        cardFile = discord.File(cardPath,filename=f'{self.modelId}.png')
        await interaction.response.send_message(file=cardFile, ephemeral=False)
        self.stop()

调用代码:

ASCB = AlphaStrikeCardButtons(name=modelName,id=modelId)
await interaction.response.send_message("Please click the button:",ephemeral=True,view=ASCB)

传入的modelName是'Supernova 5'、modelId是'8132',但按钮显示标签是"Supernova 2",custom_id是asc3133(类默认值)。如果不设置类的默认值(设为None),会报错:

In data.components.0.components.0.label: This field is required

明明传了参数,却提示未传入值,请问为什么Python会忽略__init__中设置的变量值,怎么确保使用传入的参数?

问题原因与解决方法

原因分析

@discord.ui.button装饰器是在类定义阶段执行的,此时__init__方法还未被调用,装饰器里的label=modelName和custom_id=modelId只会绑定类级别的默认值,不会等到实例化时读取self上的属性。所以不管你在__init__里给self.modelName和self.modelId赋什么值,按钮的属性已经在类创建时就固定了。

另外,按钮回调里的cardPath = f'./tmp/asc{modelId}.png'也存在问题,这里的modelId是类级变量,不是实例的self.modelId,会导致路径错误。

解决方法

不要用装饰器定义按钮,而是在__init__方法里动态创建按钮,这样就能用实例化时传入的参数:

修改后的类代码:

class AlphaStrikeCardButtons(discord.ui.View):
    def __init__(self, name, id):  
        super().__init__()
        self.modelName = name
        self.modelId = f'asc{id}'
        
        # 动态创建按钮,使用实例属性
        button = discord.ui.Button(
            label=self.modelName,
            custom_id=self.modelId,
            style=discord.ButtonStyle.blurple
        )
        # 绑定回调函数
        button.callback = self.alphaStrikeCard
        # 将按钮添加到View中
        self.add_item(button)
        
    async def alphaStrikeCard(self, interaction: discord.Interaction, button: discord.ui.Button):
        # 这里要用self.modelId
        cardPath = f'./tmp/{self.modelId}.png'
        if not os.path.isfile(cardPath):
            cardUrl = f'http://masterunitlist.info/Unit/Card/{self.modelId}'
            print(cardUrl)
            urlretrieve(cardUrl, cardPath)
        cardFile = discord.File(cardPath, filename=f'{self.modelId}.png')
        await interaction.response.send_message(file=cardFile, ephemeral=False)
        self.stop()

关键改动说明

  1. 移除类级别的modelName和modelId默认值,直接在__init__里初始化实例属性。
  2. 在__init__中手动创建discord.ui.Button实例,传入self.modelName和self.modelId作为按钮属性。
  3. 把原来的回调函数alphaStrikeCard绑定到按钮的callback属性上,再用self.add_item()把按钮添加到View里。
  4. 回调函数里的路径计算改用self.modelId,确保使用实例的属性值。

这样实例化View时,按钮的标签和custom_id就会使用传入的参数,不会再用类的默认值了。

内容的提问来源于stack exchange,提问作者Keming Lamurnogo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 09:43:15