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

Python装饰器能否访问类属性?discord.ui.button使用self报错

核心问题成因

Python类体代码在类定义阶段就会从上到下执行,@discord.ui.button(...)装饰器也是在这个阶段运行的,此时:

  • 类本身还未完成创建,不存在对应的类实例
  • self是实例方法的形参,只有实例创建完成、调用对应方法时才会被传入,类定义阶段根本不存在这个变量

所以你在装饰器参数里写self.allPages时,当前作用域找不到self标识符,直接触发self.allPages is not defined报错,这是Python语法固有执行逻辑导致的,和discord.py库本身无关。

关于装饰器访问属性的通用结论:

  • 访问类属性:仅能获取装饰器执行前已定义的类属性值,传入装饰器的是定义阶段的固定静态值,后续修改类属性不会自动同步到装饰器参数
  • 访问实例属性:完全无法在装饰器传参阶段直接访问,因为装饰器执行时类实例尚未创建。
正确修改方案

discord.py的UI组件装饰器支持实例化后动态修改属性,这也是官方推荐的动态参数实现方式,步骤如下:

  1. 装饰器参数里先给label传一个临时占位值
  2. 在__init__方法完成实例属性赋值后,直接修改对应按钮实例的label属性
  3. 如果回调逻辑里需要更新按钮显示,直接操作回调传入的button对象即可

修改后的可运行代码示例:

class ButtonView(discord.ui.View):
    def __init__(self, allPages, author, *, timeout = 180):
        super().__init__(timeout=timeout)
        self.allPages = allPages
        # 实例属性赋值完成后,动态修改按钮label
        self.current_page_button.label = self.allPages

    # 装饰器里先写占位label,custom_id保持不变即可
    @discord.ui.button(label="加载中...", style=discord.ButtonStyle.secondary, custom_id="current_page_button")
    async def current_page_button_callback(self, button, interaction):
        # 回调内如果需要更新label,直接修改button对象属性即可
        # 例:翻页后更新页码显示:button.label = f"第{self.current_page}页/共{len(self.allPages)}页"
        await interaction.response.edit_message(view=self)

注意:装饰器装饰的回调方法名是什么,discord.py就会把对应的按钮组件挂载到实例的同名属性上,所以示例里直接用self.current_page_button就能拿到按钮实例,不需要额外遍历children列表查找组件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 12:24:58