如何为Python类方法创建带参数装饰器并正确访问类实例属性
问题原因
带参数的装饰器需要多一层嵌套来接收参数,无参装饰器直接接收被装饰函数即可,但带参装饰器的执行逻辑是:
- 写
@decorator("Something")时,会先立刻执行decorator("Something") - 上一步的返回值才是真正用来装饰目标方法的装饰器函数,接收被装饰的方法作为参数
- 最终返回包装后的方法
你原来的写法没有这层接收参数的嵌套,所以导入类时装饰器就直接执行了,而且把你传的字符串参数赋值给了原本用来接收被装饰函数的foo形参,把被装饰的方法赋值给了原本的self形参,自然参数就全乱了。
正确实现方案
要封装页面跳转判断逻辑,我们可以把目标页面名称作为装饰器参数传入,包装逻辑里直接访问实例的current_page属性做判断即可:
class OtherMenu: current_page = 'algo' class MenuSidebarWebScreen(OtherMenu): # 声明为静态方法,不需要传入self @staticmethod def decorator(target_page): # 第一层:接收被装饰的类方法 def wrapper(foo): # 第二层:实际执行的包装逻辑,接收类实例self def magic(self, *args, **kwargs): # 封装跳转判断逻辑 if self.current_page == target_page: print(f'Already in the {self.current_page}, skipping menu interaction.') return # 可自定义其他通用逻辑 print("start magic") # 执行原方法 res = foo(self, *args, **kwargs) print("end magic") return res return magic return wrapper # 传入目标页面作为装饰器参数 @decorator("Home") def go_to_home_page(self): # 原方法只保留跳转逻辑即可 self.current_page = "Home" # 可复用装饰器装饰其他跳转方法 @decorator("Algo") def go_to_algo_page(self): self.current_page = "Algo"
测试效果
>>> menu = MenuSidebarWebScreen() >>> menu.current_page 'algo' >>> menu.go_to_home_page() start magic end magic >>> menu.current_page 'Home' >>> menu.go_to_home_page() Already in the Home, skipping menu interaction.
该实现满足所有需求:
- 装饰器接收自定义参数,不会在导入类时错误执行逻辑
- 包装层可以正常拿到类实例
self,访问实例属性current_page做判断 - 公共的跳转前置判断逻辑封装在装饰器中,各个页面跳转方法只需要保留自身的跳转实现即可
内容的提问来源于stack exchange,提问作者Vini.g.fer
相关产品推荐
相关产品推荐

