)
函数参数里*的作用仅限关键字传参keyword-only arguments1. 核心作用*单独放在函数形参列表中代表*后面所有参数调用时只能用「关键字传参」不能用位置传参。看你代码defexecute_agent_plan(*,run_id:int,task:str,task_type:str,top_k:int,plan:list[AgentPlanStep],memory:dict[str,Any],)-dict:*在最开头意味着这个函数所有参数都必须关键字传入。2. 正反示例✅ 合法调用关键字传参execute_agent_plan(run_id1,task查询数据,task_typesearch,top_k5,plan[],memory{})❌ 非法调用位置传参直接报错 TypeError# 报错execute_agent_plan() takes 0 positional arguments but 6 were givenexecute_agent_plan(1,查询数据,search,5,[],{})3. 两种常见*用法区分① 单独*强制后面只能关键字传参deffunc(a,*,b,c):passfunc(1,b2,c3)# okfunc(1,2,3)# 报错②*args可变位置参数收集多余位置参数deffunc(a,*args,b,c):passfunc(1,99,100,b2,c3)4. 为什么工程代码Agent/后端喜欢这么写可读性极强调用时每个参数都带名字一眼看懂含义不会传错顺序接口稳定后续新增参数、调整参数顺序不会破坏旧调用代码适合参数多的函数像你这个Agent执行计划6个入参避免位置混淆框架/工具库标准规范FastAPI、LangChain、自定义Agent系统大量使用。5. 补充小细节*本身不接收任何值只是语法分隔符*前面可以放普通位置参数后面强制关键字defdemo(x,*,y,z):...demo(1,y2,z3)# 允许x位置传y/z必须关键字你的代码*在第一个位置代表无任何位置参数全部强制关键字。*args/**kwargs 两个核心符号1.*args处理「位置参数」作用收集所有多余的位置传参打包成元组 tuple。defdemo(a,*args):print(a)print(args,type(args))demo(10,20,30,40)# a 10# args (20, 30, 40) 元组解包调用时用*把列表/元组拆开变成多个位置参数nums[1,2,3]demo(0,*nums)# 等价 demo(0,1,2,3)关键规则只要出现*args它后面的普通参数必须关键字传参deff(x,*args,y):passf(1,2,3,y99)# 合法# f(1,2,3,99) 报错2.**kwargs处理「关键字参数」作用收集所有多余的关键字传参打包成字典 dict。defdemo(a,**kwargs):print(a)print(kwargs,type(kwargs))demo(10,b20,c30)# a 10# kwargs {b:20, c:30} 字典解包调用时用**把字典拆开批量传关键字参数params{x:1,y:2}demo(0,**params)# 等价 demo(0, x1, y2)限制**kwargs必须放在所有参数最后不能后面跟普通参数# 语法报错kwargs后不能有cdefbad(a,**kwargs,c):pass组合写法工程最常用deffunc(a,*args,b,c,**kwargs):pass执行逻辑顺序固定位置参数a多余位置全部进args元组args之后b、c只能关键字传剩下所有自定义关键字进入kwargs字典调用示例func(1,2,3,b10,c20,d30,e40)# a1# args(2,3)# b10 c20# kwargs{d:30,e:40}*单独分隔符 vs*args对比def f(*, x, y)无可变位置参数全部参数强制关键字不能多传位置值。def f(*args, x, y)允许传任意多位置参数给 argsx、y 仍必须关键字传入。速记口诀单星*→ 管位置参数打包成元组双星**→ 管关键字参数打包成字典函数定义先普通参数 →*args→ 仅限关键字参数 →**kwargs函数调用*拆列表/元组**拆字典