Python装饰器能否访问类属性?discord.ui.button使用self报错
核心问题成因
Python类体代码在类定义阶段就会从上到下执行,@discord.ui.button(...)装饰器也是在这个阶段运行的,此时:
- 类本身还未完成创建,不存在对应的类实例
self是实例方法的形参,只有实例创建完成、调用对应方法时才会被传入,类定义阶段根本不存在这个变量
所以你在装饰器参数里写self.allPages时,当前作用域找不到self标识符,直接触发self.allPages is not defined报错,这是Python语法固有执行逻辑导致的,和discord.py库本身无关。
关于装饰器访问属性的通用结论:
- 访问类属性:仅能获取装饰器执行前已定义的类属性值,传入装饰器的是定义阶段的固定静态值,后续修改类属性不会自动同步到装饰器参数
- 访问实例属性:完全无法在装饰器传参阶段直接访问,因为装饰器执行时类实例尚未创建。
正确修改方案
discord.py的UI组件装饰器支持实例化后动态修改属性,这也是官方推荐的动态参数实现方式,步骤如下:
- 装饰器参数里先给label传一个临时占位值
- 在
__init__方法完成实例属性赋值后,直接修改对应按钮实例的label属性 - 如果回调逻辑里需要更新按钮显示,直接操作回调传入的
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
相关产品推荐
相关产品推荐

