Python中为@staticmethod绑定属性后无法访问的问题
问题原因及解决办法
原因分析
staticmethod装饰器返回的是类实例:用@staticmethod装饰hello_fn后,得到的不是原函数本身,而是staticmethod类的对象。你在build_hello里给这个staticmethod实例添加了first_name属性,此时调用hello_fn()能正常执行,是因为staticmethod实现了__call__方法,会自动委托调用底层的原函数。- 类属性访问触发描述符逻辑:当把
staticmethod实例赋值给类变量后,通过World.hello_fn访问时,会触发staticmethod的__get__方法(它是Python的描述符),这个方法会返回底层的原函数,而非你添加了属性的staticmethod实例。由于first_name属性绑定在staticmethod实例上,不在原函数上,所以外部访问时找不到该属性。
解决方案
方法一:先给原函数加属性,再用装饰器包装(推荐)
调整build_hello的执行顺序,先给未装饰的原函数绑定属性,再用staticmethod包装,这样属性会保留在原函数上,通过类访问时就能正常获取:
def build_hello(name: str): def hello_fn(): return "hello my name is " # 先给原函数绑定属性 hello_fn.first_name = name # 再用staticmethod装饰 static_hello = staticmethod(hello_fn) print(static_hello() + hello_fn.first_name) return static_hello class World: hello_fn = build_hello("bob") # 正常访问属性 print(World.hello_fn.first_name) # 输出: bob
方法二:直接获取类中的staticmethod实例(不推荐)
如果不想修改build_hello的结构,可以通过类的__dict__直接获取原始的staticmethod实例(绕过描述符的__get__逻辑):
# 针对你原本的代码,这样能访问到属性 print(World.__dict__['hello_fn'].first_name) # 输出: bob
这种方式属于取巧写法,可读性和维护性较差,优先推荐方法一。
内容的提问来源于stack exchange,提问作者Coldchain9
相关产品推荐
相关产品推荐

