You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python装饰器中生成值并传递给被装饰函数?

在Python装饰器中注入值到被装饰函数

基础解决方案(硬编码参数名)

直接在装饰器的最内层wrapped函数中完成值的计算与注入,修改后的代码如下:

from flask import request, abort

def check_user_agent(allowed_agents):
    def inner_decorator(f):
        def wrapped(*args, **kwargs):
            lowercase_agent = request.user_agent.string.lower()
            if lowercase_agent not in allowed_agents:
                abort(401, "This agent is not allowed")
            # 将小写后的agent值注入到kwargs,对应被装饰函数的lc_agent参数
            kwargs['lc_agent'] = lowercase_agent
            # 若希望保留调用函数时传入的lc_agent值,改用下面这行:
            # kwargs.setdefault('lc_agent', lowercase_agent)
            return f(*args, **kwargs)
        return wrapped
    return inner_decorator

调用示例(原有代码无需修改,lc_agent会被自动赋值):

@check_user_agent(['curl'])
def get(lc_agent = None):
    return {'message':'Gotten', 'user_agent': lc_agent}

进阶解决方案(动态适配参数名)

如果不想硬编码参数名,可以通过以下两种方式优化:

方式1:装饰器自定义参数名

给装饰器增加参数,指定要注入的参数名:

from flask import request, abort

def check_user_agent(allowed_agents, agent_param='lc_agent'):
    def inner_decorator(f):
        def wrapped(*args, **kwargs):
            lowercase_agent = request.user_agent.string.lower()
            if lowercase_agent not in allowed_agents:
                abort(401, "This agent is not allowed")
            kwargs[agent_param] = lowercase_agent
            return f(*args, **kwargs)
        return wrapped
    return inner_decorator

调用时可自定义参数名:

@check_user_agent(['curl'], agent_param='user_agent')
def get(user_agent = None):
    return {'message':'Gotten', 'user_agent': user_agent}

方式2:自动检测函数参数

用inspect模块检查被装饰函数的参数列表,避免注入不存在的参数导致报错:

import inspect
from flask import request, abort

def check_user_agent(allowed_agents):
    def inner_decorator(f):
        # 获取被装饰函数的参数列表
        sig = inspect.signature(f)
        func_params = list(sig.parameters.keys())
        
        def wrapped(*args, **kwargs):
            lowercase_agent = request.user_agent.string.lower()
            if lowercase_agent not in allowed_agents:
                abort(401, "This agent is not allowed")
            # 仅当函数存在目标参数时才注入
            if 'lc_agent' in func_params:
                kwargs['lc_agent'] = lowercase_agent
            return f(*args, **kwargs)
        return wrapped
    return inner_decorator

核心逻辑说明

  • 注入操作必须放在wrapped函数中,因为这里是拦截被装饰函数调用的入口,所有参数都会经过此处。
  • 修改kwargs是最稳妥的方式,既不会破坏原有的位置参数args,也能精准传递指定参数。
  • 使用kwargs.setdefault()替代直接赋值时,仅当参数未被调用者传入时,才会注入装饰器生成的值。

内容的提问来源于stack exchange,提问作者Wige

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 19:45:12