如何实现可为被装饰可调用对象添加任意命名属性的Python装饰器?
解决Python动态添加任意命名属性的装饰器问题
需求是实现一个装饰器attributes,能为被装饰的可调用对象添加任意数量的命名属性,示例如下:
@attributes(foo='this', bar='exactly') # 需要实现这个装饰器! def fun1(i): return i * 2 assert fun1.foo == 'this' assert fun1.bar == 'exactly'
你之前尝试的代码无法正常工作,问题出在循环里的属性赋值方式:
def attributes(**kwargs): def _inner(func): for k, v in kwargs.items(): func.k = v # 这里的k是字面量,不是循环变量k的值! return func return _inner
这段代码里,func.k = v会把属性名固定为k,而不是你传入的foo、bar这些参数名,每次循环都会覆盖func.k的值,最终只会留下最后一个键值对的属性值,且属性名是k,完全不符合需求。
正确的实现方式是使用Python内置的setattr()函数,它可以动态地根据变量设置对象属性:
def attributes(**kwargs): def _inner(func): for attr_name, attr_value in kwargs.items(): setattr(func, attr_name, attr_value) return func return _inner
这样循环时,每次都会把kwargs里的键作为属性名,对应的值作为属性值,给被装饰的函数动态添加属性。测试这个实现,你提供的断言语句都能顺利通过,完全满足需求。
内容的提问来源于stack exchange,提问作者Asclepius
相关产品推荐
相关产品推荐

