Python如何让高阶函数返回的函数在异常中显示指定的函数名
根因说明
你修改__name__属性不生效的核心原因是:Python触发参数不匹配这类和函数定义强相关的异常时,读取的是函数底层代码对象的__code__.co_name属性,而非开发者通常修改的__name__属性。functools.wraps默认只会复制__name__等表层元数据,不会修改代码对象内的名称值,因此异常信息里仍然会显示嵌套定义的new_func名称。
解决方案
Python 3.8及以上版本可以直接通过代码对象的replace方法修改co_name字段,实现异常信息中显示自定义名称的需求,完整实现如下:
from functools import wraps def create_function(func, arguments: dict): @wraps(func) def new_func(x): return func(x, **arguments) # 修改代码对象的内置名称,让异常信息读取该值 new_func.__code__ = new_func.__code__.replace(co_name=func.__name__) # 可选:修改全限定名,适配嵌套函数/类方法的场景 new_func.__qualname__ = func.__qualname__ return new_func
效果测试
调用测试代码:
f = create_function(sum, {}) print(f.__name__) f()
输出结果完全符合预期:
sum TypeError: sum() missing 1 required positional argument: 'x'
低版本Python兼容方案
如果你使用的是Python 3.8以下的版本,没有内置的code.replace方法,可以通过types.FunctionType手动构造新的函数对象实现相同效果:
from functools import wraps import types def create_function(func, arguments: dict): @wraps(func) def new_func(x): return func(x, **arguments) # 构造新的code对象,替换名称字段 original_code = new_func.__code__ new_code = types.CodeType( original_code.co_argcount, original_code.co_posonlyargcount, original_code.co_kwonlyargcount, original_code.co_nlocals, original_code.co_stacksize, original_code.co_flags, original_code.co_code, original_code.co_consts, original_code.co_names, original_code.co_varnames, original_code.co_filename, func.__name__, # 替换为原函数名 original_code.co_firstlineno, original_code.co_lnotab, original_code.co_freevars, original_code.co_cellvars ) new_func.__code__ = new_code new_func.__qualname__ = func.__qualname__ return new_func
内容的提问来源于stack exchange,提问作者Drachen
相关产品推荐
相关产品推荐

