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

Python 2.7中包装函数后如何保留原函数的参数名?

在Python 2.7中让装饰后的函数保留原参数名

问题根源

__code__是Python函数对象的只读属性,functools.wraps仅能复制函数的元数据(如__name__、__doc__),无法修改或替换包装函数(wrapper)的__code__。因此直接访问f.__code__.co_varnames得到的是wrapper自身的('args', 'kwargs'),而非原函数的参数名。

可行解决方案

方案1:递归获取最内层原函数

利用functools.wraps给包装函数添加的__wrapped__属性,递归找到最原始的函数,再访问其__code__.co_varnames:

from functools import wraps

def get_original_func(func):
    # 递归遍历__wrapped__属性,直到找到最内层原函数
    while hasattr(func, '__wrapped__'):
        func = func.__wrapped__
    return func

def deco(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

@deco
def f(a):
    pass

original_func = get_original_func(f)
print original_func.__code__.co_varnames  # 输出 ('a',)

方案2:给包装函数添加自定义属性

在装饰器中直接将原函数的参数名存储为包装函数的自定义属性,后续直接访问该属性即可:

from functools import wraps

def deco(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    # 给包装函数添加自定义属性,存储原函数的参数名
    wrapper.__original_co_varnames__ = func.__code__.co_varnames
    return wrapper

@deco
def f(a):
    pass

print f.__original_co_varnames__  # 输出 ('a',)

方案3:结合inspect模块获取参数

通过inspect模块的工具函数,配合递归获取原函数,直接提取参数列表:

import inspect
from functools import wraps

def get_original_func(func):
    while hasattr(func, '__wrapped__'):
        func = func.__wrapped__
    return func

def deco(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

@deco
def f(a):
    pass

original_func = get_original_func(f)
argspec = inspect.getargspec(original_func)
print tuple(argspec.args)  # 输出 ('a',)

说明

functools.wraps本身没有提供修改参数名相关属性的能力,因为__code__属性的只读特性无法绕过。上述方案都是通过间接方式获取原函数的参数信息,而非修改包装函数的__code__。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 01:20:24