Python中的函数参数(位置参数、默认参数、可变参数)
前言Python 的函数参数比很多语言灵活既支持按位置传也支持按关键字传既能接固定数量的参数也能接任意数量的参数。灵活带来的代价是规则细细节记错就会写出「本地能跑、换个调用方式就炸」的代码。最常见的三个误解以为默认参数每次调用都会重新创建。实际上默认值在def执行的那一刻就求值并绑定好了所以可变的默认值会被所有调用共享。以为*args拿到的就是「列表」。它拿到的是元组tuple**kwargs拿到的是字典dict。以为 Python 是「值传递」或「引用传递」之一。准确的说法是对象引用传递call by object reference也叫「按共享传递」函数拿到的是对象引用的副本改不改得到调用方取决于你操作的是不可变对象还是可变对象。本文把四类参数、参数顺序规则、打包与解包、以及默认参数和可变参数上的坑一次讲清楚。一、四类参数与书写顺序一个完整的函数签名可以同时包含下面几部分顺序是固定的def 函数名(位置参数..., 带默认值的位置参数..., *可变位置参数, 仅关键字参数..., **可变关键字参数)# 适用于 Python 3.8def func(a, b2, *args, c, d4, **kwargs):print(a , a)print(b , b)print(args , args, type(args).__name__)print(c , c)print(d , d)print(kwargs , kwargs)func(1, 3, 5, 6, c7, x8, y9)a 1b 3args (5, 6) tuplec 7d 4kwargs {x: 8, y: 9}几个要点*args把多出来的位置实参收成一个元组**kwargs把多出来的关键字实参收成字典。args/kwargs只是习惯名字起作用的是*和**。*args之后的参数如上面的c变成仅关键字参数调用时必须写成c7。单独一个*可以不收集任何东西只用来把后面的参数强制变成仅关键字def f(a, *, b)。这个语法从Python 3.0就有。仅位置参数用/表示需要 Python 3.8 及以上def f(a, b, /, c)里a、b只能按位置传。不能在有默认值的参数后面再放没有默认值的参数def f(a1, b)是SyntaxError。二、默认参数只求值一次这是默认参数上最具「迷惑性」的行为。默认值表达式在函数定义时求值一次之后每次调用复用同一个对象。# 适用于 Python 3.8def append_item(item, box[]):box.append(item)return boxprint(append_item(1)) # [1]print(append_item(2)) # [1, 2] —— 不是 [2]正确写法是把默认值设成None在函数体内按需创建# 适用于 Python 3.8def append_item(item, boxNone):if box is None:box []box.append(item)return boxprint(append_item(1)) # [1]print(append_item(2)) # [2]注意判断条件是is None而不是if not box——后者在调用方显式传入一个空列表时也会走「新建」分支把调用方的意图覆盖掉。三、参数传递改不改得动调用方函数拿到的是对象引用的副本。所以结论很简单在函数内重新赋值x ...只影响函数内的名字不影响调用方。在函数内原地修改可变对象x.append(...)、x[0] ...调用方会看到变化。# 适用于 Python 3.8def rebind(x):x [9, 9, 9] # 只是让局部名字指向新对象def mutate(x):x.append(9) # 原地改调用方看得见data [1, 2, 3]rebind(data)print(data) # [1, 2, 3]mutate(data)print(data) # [1, 2, 3, 9]不可变对象int、str、tuple、frozenset根本没法原地改所以「传进去改一改」这类写法对它们一定无效。四、调用时的解包*和**在调用时也有用作用是把一个可迭代对象/字典拆成多个实参# 适用于 Python 3.8def show(a, b, c):print(a, b, c)nums [1, 2, 3]show(*nums) # 1 2 3opts {a: 1, b: 2, c: 3}show(**opts) # 1 2 3Python 3.5 及以上还允许在一次调用里写多个解包# 适用于 Python 3.5def total(*nums):return sum(nums)first, second [1, 2], [3, 4]print(total(*first, *second)) # 10五、完整示例一个灵活的日志函数# 适用于 Python 3.8def log(message, levelINFO, *tags, sep-, upperFalse, **extra):level 有默认值tags 收集多余位置实参sep、upper 是仅关键字参数extra 收集多余关键字实参。if upper:message message.upper()tag_part sep.join(tags) if tags else noneparts [f[{level}], message, ftags{tag_part}]for key in sorted(extra):parts.append(f{key}{extra[key]})return .join(parts)if __name__ __main__:print(log(started))print(log(started, WARN, db, cache, upperTrue))print(log(done, ERROR, userann, code500, sep))[INFO] started tagsnone[WARN] STARTED tagsdb-cache[ERROR] done tagsnone code500 userann注意log(done, ERROR, userann, code500, sep)这一句user、code、sep都是关键字所以正确落到了各自的参数上不会误进*tags。六、用 inspect 读参数签名不确定一个函数到底接受哪些参数时不要靠猜用标准库inspect直接读出来。inspect.signature()返回一个Signature对象每个参数还有kind用来说明它属于哪一类——POSITIONAL_ONLY、POSITIONAL_OR_KEYWORD、VAR_POSITIONAL、KEYWORD_ONLY、VAR_KEYWORD# 适用于 Python 3.8import inspectdef demo(a, b2, *args, c, **kwargs):passsig inspect.signature(demo)for name, param in sig.parameters.items():print(name, param.kind.name, param.default)a POSITIONAL_OR_KEYWORD class inspect._emptyb POSITIONAL_OR_KEYWORD 2args VAR_POSITIONAL class inspect._emptyc KEYWORD_ONLY class inspect._emptykwargs VAR_KEYWORD class inspect._empty没有默认值的参数param.default会是哨兵对象inspect.Parameter.empty上面打印出来就是那串class inspect._empty。这对读第三方库的签名、写自己的参数校验很有用比看文档猜靠谱得多。常见坑点可变默认参数❌def f(item, box[])多次调用共享同一个列表 ✅def f(item, boxNone)函数体内if box is None: box []默认值是函数调用❌def f(ttime.time())只在定义时取一次不刷新 ✅def f(tNone)函数体内t t if t is not None else time.time()误以为*args是列表❌args.append(1)会报AttributeError元组没有append✅ 需要列表就args list(args)只读时直接按元组用在*args后面写普通参数❌def f(*args, b)却调用f(1, 2, 3)b缺少值 ✅*args之后的参数是仅关键字必须写f(1, 2, 3, b4)用not box判断是否传了参数❌if not box: box []调用方传空列表会被悄悄替换 ✅if box is None: box []只区分「没传」这一种情况以为改函数内参数名会影响调用方❌ 在函数里x x [1]就指望调用方的列表被改 ✅ 要影响调用方就原地改x [1]对列表是原地否则把结果return出去混淆mysort(l, key)与mysort(l, keykey)❌f(data, len)以为传给了key实际落到了下一个位置参数 ✅ 明确写关键字f(data, keylen)旧式元组参数解包❌def f((a, b)):这种 Python 2 的写法在 Python 3 里是语法错误 ✅def f(pair):函数体内a, b pair总结参数类型写法传参方式收到的类型位置或关键字a位置或a1原对象带默认值a1可省略原对象可变位置*args多余位置实参tuple仅关键字*之后如def f(a, *, b)必须b...原对象仅位置/之前3.8只能按位置原对象可变关键字**kwargs多余关键字实参dict记两条主线就够了默认值在定义时求值一次所以永远不要把可变对象直接当默认值参数传递传的是对象引用能不能改到调用方取决于操作的是可变对象还是不可变对象。把这两条记牢参数相关的诡异现象基本都能自己解释清楚。

相关新闻

Nacos 2.5.0在麒麟ARM上适配达梦数据库的源码级实践

Nacos 2.5.0在麒麟ARM上适配达梦数据库的源码级实践

简介:编译好的Nacos 2.5.0 Linux版本已针对达梦数据库与麒麟ARM系统完成国产化适配,适合在信创替代场景中需落地微服务注册与配置中心的开发运维人员,也适合关注开源组件国产化改造的技术团队。资源包约148MB,共17个文件&#xff…

2026/10/16 6:55:58 阅读更多 →
Meld可视化对比:1分钟定位配置文件改动,告别肉眼排错

Meld可视化对比:1分钟定位配置文件改动,告别肉眼排错

记上周五一件事。某个服务的前端配置在发布前被我顺手多改了一行,当时脑子里全是“就一个开关,真值改回去了”,结果重启之后进程直接起不来。日志翻了三遍没有有效报错,最后只能靠肉眼去和另一套环境的配置文件逐句比对&#xff0…

2026/10/16 6:55:58 阅读更多 →
Apifox全局token配置:变量继承与自动写入,告别手动鉴权

Apifox全局token配置:变量继承与自动写入,告别手动鉴权

用过Apifox调试接口的人,应该都经历过这种局面:登录接口拿到一个token,然后打开其他接口,手动在Header里粘上Authorization: Bearer xxx;token过期了,再回去登录,再一个个接口重新粘一遍。如果只…

2026/10/16 6:55:58 阅读更多 →

最新新闻

airllm分层加载实战:8GB显存跑70B大模型推理

airllm分层加载实战:8GB显存跑70B大模型推理

1. 当大模型装不进显卡时,我在想什么第一次看到 airllm 这个项目名的时候,我正对着自己那台只有 8GB 显存的旧笔记本发愁。想跑一个 70B 参数级别的大语言模型,按常规思路算一下显存占用:光是模型权重以 FP16 精度加载&#xff0c…

2026/10/16 7:34:10 阅读更多 →
宏组学关联分析新利器MaAsLin3:两部件回归与稳健估计

宏组学关联分析新利器MaAsLin3:两部件回归与稳健估计

Nature Methods上那篇MaAsLin3的论文,在宏组学关联分析这个领域里算是个不大不小的里程碑。这几年做微生物组、代谢组与宿主表型关联研究的人,对MaAsLin系列应该都不陌生:它用多变量线性模型,把物种丰度、通路丰度或者代谢物丰度矩…

2026/10/16 7:34:10 阅读更多 →
图的四种存储结构本质:从邻接矩阵到邻接多重表的技术演进

图的四种存储结构本质:从邻接矩阵到邻接多重表的技术演进

1. 这份笔记不是“背了就能考高分”的速成口诀,而是帮你真正看懂图结构的底层逻辑“数据结构考研笔记(十五)——图的存储结构邻接矩阵、邻接表、十字链表、临界多重表的概念”,光看标题,很多人第一反应是:又…

2026/10/16 7:34:10 阅读更多 →
综合能源系统P2G与碳捕集耦合的epsilon约束法优化复现

综合能源系统P2G与碳捕集耦合的epsilon约束法优化复现

说句实在话,看到标题里带“SCI一区复现”的时候,我第一反应是又双叒叕一篇综合能源系统运行优化。但真把这篇Energy期刊的文章拆开读完之后,我发现它跟很多“挂羊头卖狗肉”的IES文章不一样:一是它把P2G和碳捕集设备做成了物理耦合…

2026/10/16 7:34:10 阅读更多 →
图的四种存储结构选型:邻接矩阵、邻接表、十字链表与邻接多重表深度对比

图的四种存储结构选型:邻接矩阵、邻接表、十字链表与邻接多重表深度对比

1. 为什么图的四种存储结构不能只背定义?——从一道真题切入去年某高校考研真题里有这么一道题:给定一个含100个顶点、稀疏分布的有向图,要求支持高频的“查询某条边是否存在”和“遍历所有出边”操作,请分析邻接矩阵、邻接表、十…

2026/10/16 7:34:10 阅读更多 →
具身智能入门与落地:从数据闭环到系统化工程实践

具身智能入门与落地:从数据闭环到系统化工程实践

这些天 AI 圈子最热闹的话题,莫过于 GPT-6 Astra。各群从白天讨论到深夜,先聊模型,后聊机器人,最后一定会落到具身智能。我第一反应不是去搜测试视频,而是想起这个月已经有三四个朋友跑来问我:“具身智能到…

2026/10/16 7:33:10 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →