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

Python使用装饰器转换函数参数时tuple不支持赋值错误如何解决

报错根因

Python 中函数的*args参数本质是只读元组,不支持直接修改元素,即使单个元素本身支持修改,也不能对元组执行下标赋值操作,这就是触发TypeError: 'tuple' object does not support item assignment的直接原因。
另外原代码逻辑存在反向错误:判断条件if type(args[i]) == args1[i]表示「参数当前类型等于目标转换类型时才执行转换」,和预期的「非目标类型时转换为目标类型」完全相反。

原有代码修复方案

只需要把元组args转为可修改的列表,同时修正判断逻辑即可,修复后代码如下:

def check_args(*args1):
    def decorator(func):
        def wrapper(*args, **kwargs):
            # 将只读元组转为可修改的列表
            args_list = list(args)
            for i in range(len(args_list)):
                # 修正判断逻辑:当前类型不等于目标类型时再转换
                if type(args_list[i]) != args1[i]:
                    args_list[i] = args1[i](args_list[i])
            result = func(*args_list, **kwargs)
            return result
        return wrapper
    return decorator

# 测试示例
@check_args(str, str)
def function(arg1, arg2):
    print(type(arg1), type(arg2))
    print(arg1, arg2)

function(5, 10)
# 输出:
# <class 'str'> <class 'str'>
# 5 10
更完善的参数类型转换装饰器方案

上面的基础版本只支持处理位置参数,无法处理关键字参数,也没有做参数数量匹配的异常兼容,可参考下面的增强版本,支持位置、关键字参数统一处理:

import inspect
from functools import wraps

def type_convert(*pos_types, **kw_types):
    def decorator(func):
        # 保留原函数的元信息
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 获取函数参数签名,绑定当前传入的所有参数
            sig = inspect.signature(func)
            bound_args = sig.bind(*args, **kwargs)
            bound_args.apply_defaults()
            
            # 处理位置参数类型转换
            for idx, param_name in enumerate(list(sig.parameters.keys())[:len(pos_types)]):
                target_type = pos_types[idx]
                if not isinstance(bound_args.arguments[param_name], target_type):
                    bound_args.arguments[param_name] = target_type(bound_args.arguments[param_name])
            
            # 处理关键字参数类型转换
            for param_name, target_type in kw_types.items():
                if param_name in bound_args.arguments and not isinstance(bound_args.arguments[param_name], target_type):
                    bound_args.arguments[param_name] = target_type(bound_args.arguments[param_name])
            
            return func(*bound_args.args, **bound_args.kwargs)
        return wrapper
    return decorator

# 测试示例
@type_convert(str, int, age=float)
def user_info(name, id, age):
    print(f"name类型:{type(name)}, id类型:{type(id)}, age类型:{type(age)}")
    print(f"name={name}, id={id}, age={age}")

# 混合位置参数、关键字参数调用
user_info(123, "1001", age="18.5")
# 输出:
# name类型:<class 'str'>, id类型:<class 'int'>, age类型:<class 'float'>
# name=123, id=1001, age=18.5

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 09:18:03