Python装饰器新手问询:如何将函数输出传递给装饰器?
当然可行!这样传递值给装饰器的方法
嘿,作为装饰器新手,你能想到这个需求已经很棒了——完全可以把test返回的to_decorator值传递给装饰器,不过得调整下代码结构,因为你当前的装饰器逻辑是在message函数执行前运行的,而to_decorator是message内部生成的局部变量,装饰器默认拿不到它。
下面给你两种简单易懂的实现方式:
方法1:让被装饰函数返回「原结果 + 需要传递的值」
这是最直观的方式,让message函数把要传给装饰器的to_decorator和自身的返回值一起返回,装饰器调用原函数后就能捕获到这个值:
def test(*args): return "from test" def decorate(function): def wrap_function(*args, **kwargs): # 调用原函数,拿到返回的元组(原结果 + to_decorator) original_result, to_decorator = function(*args, **kwargs) # 现在装饰器可以随意使用to_decorator了,比如打印、存储等 print(f"装饰器成功拿到to_decorator的值: {to_decorator}") # 如果需要保持原函数的返回值,只返回original_result即可 return original_result return wrap_function class Sample(): @decorate def message(self, *args, **kwargs): to_decorator = test(*args) print(to_decorator) # 返回原函数结果(这里我设为"message执行完成")和to_decorator return "message执行完成", to_decorator # 测试一下 sample_instance = Sample() sample_instance.message("测试参数")
运行这段代码,你会看到输出:
from test 装饰器成功拿到to_decorator的值: from test message执行完成
方法2:用闭包变量存储值(不改变原函数返回值)
如果你不想修改message的返回值,可以在装饰器里定义一个闭包变量,让message函数内部把to_decorator赋值给这个变量:
def test(*args): return "from test" def decorate(function): # 定义闭包变量,用来存储to_decorator的值 captured_to_decorator = None def wrap_function(*args, **kwargs): nonlocal captured_to_decorator # 调用原函数,同时把闭包变量的引用传进去 original_result = function(*args, **kwargs, decorator_var=captured_to_decorator) # 现在装饰器可以使用captured_to_decorator了 if captured_to_decorator is not None: print(f"装饰器捕获到的to_decorator: {captured_to_decorator}") return original_result # 可选:给wrap_function加个属性,方便外部获取这个值 wrap_function.get_captured_value = lambda: captured_to_decorator return wrap_function class Sample(): @decorate def message(self, *args, **kwargs): to_decorator = test(*args) print(to_decorator) # 把to_decorator赋值给装饰器的闭包变量 kwargs['decorator_var'].__setattr__('__value__', to_decorator) return "message执行完成" # 测试 sample_instance = Sample() sample_instance.message("测试参数") # 外部也能获取装饰器捕获的值 print(f"外部获取的捕获值: {sample_instance.message.get_captured_value()}")
核心逻辑说明
装饰器的本质是闭包函数包裹原函数,所以只要原函数能把需要传递的值暴露出来(不管是通过返回值,还是修改装饰器的闭包变量),装饰器就能拿到这个值。你原来的代码里,to_decorator是message的局部变量,装饰器无法直接访问,所以需要通过上述方式让两者建立传递通道。
内容的提问来源于stack exchange,提问作者Ravi Kiran G
相关产品推荐
相关产品推荐

