Python函数:参数传递顺序的强制规则详解
Python函数参数传递顺序的强制规则详解一、开篇一张图看清Python参数的全貌在前几篇文章中我们分别学习了位置参数、关键字参数、默认参数、*args和**kwargs。但当你把它们组合在一起时有一个关键问题这些不同类型的参数应该按什么顺序排列⌨️ Python的答案是强制的、固定的顺序。你不能随心所欲地排列——语法层面就会报错。# Python函数参数的完整定义顺序从前往后# 1. 位置专用参数 / 之前 Python 3.8# 2. 普通参数 / 和 * 之间# 3. 可变位置参数 *args# 4. 关键字专用参数 * 或 *args 之后# 5. 可变关键字参数 **kwargs 必须放在最后# 下面我们逐一拆解为什么是这个顺序 理解这个顺序规则不仅是记住语法——它反映了Python函数调用的底层逻辑。一旦你理解了为什么就永远不会写错了。二、参数分类全景图2.1 五种参数类型# ⌨️ Python函数的参数可以分为五大类# 第一类位置专用参数Positional-Only# 在 / 之前定义只能用位置传递deffunc1(a,b,/):a和b只能用位置传递pass# 第二类位置或关键字参数Positional-or-Keyword# 默认的参数类型既可以用位置也可以用关键字deffunc2(a,b):a和b位置或关键字都可以pass# 第三类可变位置参数*args# 用 * 标记收集任意数量的位置参数deffunc3(a,*args):args收集多余的位置参数pass# 第四类关键字专用参数Keyword-Only# 在 * 或 *args 之后定义只能用关键字传递deffunc4(*,a,b):a和b只能用关键字传递pass# 第五类可变关键字参数**kwargs# 用 ** 标记收集任意数量的关键字参数deffunc5(**kwargs):kwargs收集多余的关键字参数pass2.2 每条规则都有它的道理# 规则一普通参数必须在默认参数之前# 原因如果默认参数在前面位置传参就无法确定哪个参数被省略了# ✅ 正确deff1(a,b1):pass# ❌ 错误# def f1(a1, b): pass# SyntaxError: non-default argument follows default argument# 规则二*args必须在普通参数之后# 原因*args会贪婪地收集所有位置参数如果放在前面后面的参数永远得不到值# ✅ 正确deff2(a,*args):pass# ❌ 错误# def f2(*args, a): pass # a永远得不到位置参数的值只能用关键字传# 规则三**kwargs必须在*args之后# 原因**kwargs收集关键字参数而*args收集位置参数两者不冲突# 但如果**kwargs在前面会干扰*args的识别# ✅ 正确deff3(*args,**kwargs):pass# ❌ 错误# def f3(**kwargs, *args): pass# SyntaxError: invalid syntax# 规则四**kwargs必须在最后# 原因**kwargs会收集所有剩余的关键字参数# ✅ 正确deff4(a,*args,**kwargs):pass# ❌ 错误# def f4(**kwargs, a): pass# SyntaxError: invalid syntax三、完整参数定义的语法规则3.1 标准顺序不使用位置专用参数# 最常用的参数定义顺序# def func(普通参数, ..., *args, 关键字专用参数, ..., **kwargs):# pass# 完整示例defcreate_api(method,# 1. 普通参数必选path,# 普通参数必选versionv1,# 普通参数带默认值*args,# 2. 可变位置参数timeout30,# 3. 关键字专用参数有默认值retries3,# 关键字专用参数有默认值auth_tokenNone,# 关键字专用参数可选**kwargs# 4. 可变关键字参数):创建API请求配置config{method:method,path:f/api/{version}/{path},timeout:timeout,retries:retries,auth_token:auth_token,extra_positional:args,extra_keyword:kwargs,}returnconfig# 各种调用方式print(create_api(GET,users))# {method: GET, path: /api/v1/users, timeout: 30, ...}print(create_api(POST,users,v2,timeout60,auth_tokenabc123))# {method: POST, path: /api/v2/users, timeout: 60, ...}print(create_api(GET,search,v3,extra1,extra2,timeout10,retries5,qpython,page1))# args(extra1, extra2), kwargs{q: python, page: 1}3.2 带位置专用参数的完整顺序Python 3.8# def func(位置专用参数, /, 普通参数, *args, 关键字专用参数, **kwargs):defadvanced_function(a,b,# 位置专用参数只能按位置传递/,# ← 分隔符c,d,# 普通参数位置或关键字都行*args,# 可变位置参数edefault_e,# 关键字专用参数fdefault_f,# 关键字专用参数**kwargs# 可变关键字参数):所有参数类型都齐全的函数print(f位置专用: a{a}, b{b})print(f普通参数: c{c}, d{d})print(f可变位置: args{args})print(f关键字专用: e{e}, f{f})print(f可变关键字: kwargs{kwargs})# ✅ 正确的调用方式advanced_function(1,2,3,4,5,6,eE,fF,extraEXTRA)# 位置专用: a1, b2# 普通参数: c3, d4# 可变位置: args(5, 6)# 关键字专用: eE, fF# 可变关键字: kwargs{extra: EXTRA}# ✅ 普通参数c,d可以用关键字advanced_function(1,2,d4,c3,eE,fF)# 位置专用: a1, b2# 普通参数: c3, d4 (注意关键字不按顺序)# 可变位置: args()# 关键字专用: eE, fF# 可变关键字: kwargs{}# ❌ 位置专用参数不能用关键字# advanced_function(a1, b2, c3, d4, eE, fF)# TypeError: got some positional-only arguments passed as keyword arguments: a, b# ❌ 关键字专用参数不能用位置# advanced_function(1, 2, 3, 4, E, F)# TypeError: takes 4 positional arguments but 6 were given# E和F被*args吃掉了3.3 只有没有args的情况# * 本身也可以作为分隔符——不收集任何位置参数deffunc(a,b,*,c,d): a, b: 位置或关键字 c, d: 关键字专用 print(fa{a}, b{b}, c{c}, d{d})# ✅ 正确func(1,2,c3,d4)func(a1,b2,c3,d4)# ❌ 错误# func(1, 2, 3, 4)# TypeError: takes 2 positional arguments but 4 were given# * 阻止了位置参数c和d只能用关键字# 这种模式很常用——当你确定某些参数容易混淆时defcopy_file(source,destination,*,overwriteFalse):source和destination容易混淆但至少它们可以用位置传defcopy_file_safe(*,source,destination,overwriteFalse):更安全——所有参数都必须用关键字四、PEP文档中的规范4.1 PEP 3102——关键字专用参数# PEP 31022006年引入了关键字专用参数# 这是Python 3.0中的重要改进# 在PEP 3102之前无法强制用户使用关键字传参# 只能用文档说明请使用关键字参数# PEP 3102之后defsort_items(items,*,keyNone,reverseFalse):key和reverse必须用关键字——和内置sorted()一样returnsorted(items,keykey,reversereverse)# 和内置sorted()保持一致的API风格# sorted(iterable, /, *, keyNone, reverseFalse)# 位置专用 关键字专用4.2 PEP 570——位置专用参数# PEP 5702020年Python 3.8引入了位置专用参数# 使用 / 作为分隔符# 这解决了长期存在的问题# 有些函数的参数名没有意义用户不应该用关键字传参# 标准库中大量使用位置专用参数的例子# len(obj, /) —— 你不能写 len(obj[1,2,3])# abs(x, /) —— 你不能写 abs(x-5)# int(x0, /) —— 第一个参数x只能用位置# str(object, /) —— 第一个参数object只能用位置# list(iterable(), /) —— 第一个参数iterable只能用位置# 自定义函数中使用 / 的例子defisclose(a,b,/,*,rel_tol1e-09,abs_tol0.0): 比较两个浮点数是否接近 a, b: 两个数值应该用位置传递哪个是哪个不重要 rel_tol, abs_tol: 容差配置用关键字传递更清晰 returnabs(a-b)max(rel_tol*max(abs(a),abs(b)),abs_tol)print(isclose(3.0,3.0000000001))# Trueprint(isclose(3.0,3.0000000001,rel_tol1e-11))# Falseprint(isclose(3.0,3.1,abs_tol0.2))# True五、调用时的参数传递顺序5.1 位置参数必须全部在关键字参数之前# 这是Python语法层面的强制规则deffunc(a,b,c3,d4):print(fa{a}, b{b}, c{c}, d{d})# ✅ 多种正确的调用方式func(1,2)# 全位置func(1,2,3,4)# 全位置func(a1,b2)# 全关键字func(1,2,d5)# 混用位置在前func(1,b2,c3,d4)# 混用func(1,2,c3)# 混用# ❌ 关键字参数不能在位置参数之前# func(a1, 2)# SyntaxError: positional argument follows keyword argument# ❌ 不能给同一个参数传多个值# func(1, 2, a3)# TypeError: got multiple values for argument a5.2 通过*args传递的参数占用位置deffunc(a,*args,b):b在*args后面必须用关键字传print(fa{a}, args{args}, b{b})# *args会贪婪地吃掉所有位置参数func(1,2,3,4,b5)# a1, args(2, 3, 4), b5# 如果你想让args为空b必须用关键字func(1,b2)# a1, args(), b2六、常见设计模式6.1 模式一核心选项模式最常用# ⌨️ 日常开发中最推荐的参数组织方式# 核心参数放前面位置传递选项参数放后面关键字传递deffetch_data(url,# 核心——位置传*,# ← 从这里开始都是选项methodGET,headersNone,timeout30,parse_jsonTrue,allow_redirectsTrue,max_redirects5,):获取数据——url是核心其余是选项print(f{method}{url}(timeout{timeout}s))# 使用fetch_data(https://api.example.com/users)# 简洁fetch_data(https://api.example.com/admin,methodPOST,timeout60)6.2 模式二透传模式# 当一个函数需要将参数转发给另一个函数时# *args和**kwargs是完美的工具defwith_retry(max_retries3,delay1):重试装饰器——将任意参数透传给目标函数defdecorator(func):importtimedefwrapper(*args,**kwargs):forattemptinrange(max_retries):try:returnfunc(*args,**kwargs)# 透传所有参数exceptExceptionase:ifattemptmax_retries-1:raiseprint(f重试{attempt1}/{max_retries}...)time.sleep(delay)returnwrapperreturndecoratorwith_retry(max_retries3,delay0.5)defunstable_network_call(url,methodGET,**params):不稳定的网络调用importrandomifrandom.random()0.7:raiseConnectionError(网络错误)returnf成功:{method}{url}# 调用——参数可以任意变化# unstable_network_call(https://api.example.com)# unstable_network_call(https://api.example.com, methodPOST, datahello)6.3 模式三子类重写模式# 在类的继承体系中使用*args和**kwargs保证灵活性classBaseHandler:基础处理器def__init__(self,name,**config):self.namename self.configconfig self.setup()defsetup(self):子类可以重写这个方法来初始化passclassFileHandler(BaseHandler):文件处理器def__init__(self,name,file_path,**config):# 将不需要的参数通过**config传给父类super().__init__(name,**config)self.file_pathfile_pathprint(f文件处理器初始化:{file_path}, 配置{config})classDatabaseHandler(BaseHandler):数据库处理器def__init__(self,name,connection_string,**config):super().__init__(name,**config)self.connection_stringconnection_stringprint(f数据库处理器初始化:{connection_string}, 配置{config})# 使用file_handlerFileHandler(文件处理,/tmp/data.log,max_size1024,encodingutf-8)db_handlerDatabaseHandler(数据库,mysql://localhost/mydb,pool_size10,timeout30)七、常见错误速查表# ⚠️ 以下错误按出现频率排列# 1. 默认参数在非默认参数前面# def func(a1, b): # SyntaxError!# pass# 2. **kwargs不在最后# def func(**kwargs, a): # SyntaxError!# pass# 3. *args不在**kwargs前面# def func(**kwargs, *args): # SyncError!# pass# 4. 关键字参数在位置参数前面调用时# func(a1, 2) # SyntaxError!# 5. 给同一个参数传了多个值调用时# def func(a, b): pass# func(1, a2) # TypeError!# 6. 位置专用参数用了关键字调用时# def func(a, /): pass# func(a1) # TypeError!# 7. 关键字专用参数用了位置调用时# def func(*, a): pass# func(1) # TypeError!# 8. 传了不存在的关键字参数# def func(a, b): pass# func(1, 2, c3) # TypeError!# 9. 忘了*args后面参数必须用关键字# def func(*args, a): pass# func(1, 2, 3) # TypeError! a没有值八、记忆口诀和决策树8.1 记忆口诀定义函数参数的顺序——普位可变关键可变关键 普普通参数 位位置专用参数/ 可变*args 关键关键字专用参数* 可变关键**kwargs 全展开 位置专用 / 普通 *args 关键字专用 **kwargs8.2 参数类型选型决策# 设计函数时如何选择参数类型# 决策1这个参数是核心的还是可选的# 核心 → 普通参数位置传递# 可选 → 默认参数 或 关键字专用参数# 决策2参数名有意义吗# 有 → 可以用关键字传递# 没有如数学函数→ 位置专用参数# 决策3参数容易和别的参数混淆吗# 是 → 关键字专用参数强制用名字区分# 否 → 普通参数# 决策4参数数量不确定# 是 → *args多位置或 **kwargs多关键字# 决策5这是布尔参数吗# 几乎总是 → 关键字专用参数# 因为 func(True, False) 没人看得懂# 决策6这是配置选项吗# 是 → 关键字专用参数 合理默认值九、总结Python的函数参数顺序规则看似复杂但每一层规则都有其设计上的必然性。一旦你理解了为什么是这个顺序就永远不会写错。终极参数顺序完整版def func( 位置专用参数, # / 之前——参数名无意义时用 /, # 分隔符 普通参数, # 可以位置也可以关键字——核心参数 *args, # 多余的位置参数——参数数量不定时用 关键字专用参数, # * 之后——容易混淆的选项参数 **kwargs # 最后——透传参数时用 ):✅日常最简化的实用版本deffunc(核心1,核心2,可选默认值,*,选项1默认,选项2默认,**透传):日常开发中最实用的参数模式记住好的函数签名能让代码自解释。花30秒想清楚参数的顺序和类型能为未来省下30分钟的调试时间。

相关新闻

Python笔记系统化管理与高效学习指南

Python笔记系统化管理与高效学习指南

1. Python学习笔记整理指南 作为一门应用广泛的编程语言,Python的学习过程中会产生大量零散的代码片段、知识点记录和问题解决方案。这些内容如果缺乏系统化管理,很容易变成杂乱无章的"其他Python笔记",最终失去参考价值。本文将分…

2026/10/20 19:42:53 阅读更多 →
三十分钟掌握Python Flask后台管理系统开发:Pear Admin Flask实战指南

三十分钟掌握Python Flask后台管理系统开发:Pear Admin Flask实战指南

三十分钟掌握Python Flask后台管理系统开发:Pear Admin Flask实战指南 【免费下载链接】pear-admin-flask Pear admin is a front-end development framework based on layui 项目地址: https://gitcode.com/gh_mirrors/pe/pear-admin-flask Pear Admin Flas…

2026/10/19 11:51:39 阅读更多 →
TI AM64x/AM243x时钟系统深度解析:观测时钟配置与PLL调试实战

TI AM64x/AM243x时钟系统深度解析:观测时钟配置与PLL调试实战

1. 时钟系统概述与核心价值 在嵌入式处理器,尤其是像TI AM64x/AM243x这类多核异构SoC的设计与开发中,时钟系统远不止是提供“滴答”信号的简单电路。它更像是一个精密的“心脏”和“交通指挥中心”,其稳定性和灵活性直接决定了整个系统的性能…

2026/10/18 5:08:26 阅读更多 →

最新新闻

无人机航拍电力巡检数据集:绝缘子缺陷与鸟巢识别实战

无人机航拍电力巡检数据集:绝缘子缺陷与鸟巢识别实战

1. 项目背景与数据价值剖析做电力巡检AI这几年,最深的体会是:模型结构永远不缺,缺的是能真正撑起工业场景落地的数据。数据集的类别是否完整、标注是否经得起推敲、场景是否覆盖足够的天气和光照变化,往往直接决定模型上线之后是&…

2026/10/21 5:02:00 阅读更多 →
CTF夺旗赛学习路线:从零基础到竞赛拿奖的完整指南

CTF夺旗赛学习路线:从零基础到竞赛拿奖的完整指南

如果你在计算机专业读了两年,却发现自己除了会写课设管理系统,其他什么都说不出来,那我建议你认真了解一下CTF。我招人的时候,简历上写着“CTF某赛区一等奖”的应届生,往往比那些简历里堆了三四个“XX管理系统”项目的…

2026/10/21 5:02:00 阅读更多 →
麒麟V10离线部署FFmpeg:静态编译解决动态库依赖全攻略

麒麟V10离线部署FFmpeg:静态编译解决动态库依赖全攻略

前阵子给一个跑在麒麟V10上的转码服务准备部署环境,遇到所有离线交付都躲不过的坎:目标主机没有包管理器源,也不能随便外联。我把开发机上编译好的FFmpeg直接拷贝过去,运行时立刻报出libavcodec.so.58: cannot open shared object…

2026/10/21 5:02:00 阅读更多 →
Google Maps MCP接入实战:给AI装上实时空间感知的地图眼睛

Google Maps MCP接入实战:给AI装上实时空间感知的地图眼睛

最近在整理自己AI工具链的时候,我发现一个特别有意思的缺口:模型能背出任意城市的经纬度,能写出很详细的旅行攻略,但真要它判断“从某个小区到最近的地铁站骑车要多久”,它就开始含糊其辞地给估算值了。原因也很简单—…

2026/10/21 5:02:00 阅读更多 →
lingbot-map:打通建图到导航最后一公里的地图中间件

lingbot-map:打通建图到导航最后一公里的地图中间件

1. 这个模块解决的是从建图到导航之间的“最后一公里”我第一次看到lingbot-map这个名字的时候,第一反应是:这不就是一个地图处理模块吗?但真正上手之后才意识到,它解决的核心问题不是地图“怎么画”,而是地图“怎么用…

2026/10/21 5:02:00 阅读更多 →
IDEA多模块工程:Java与Python自动化测试框架统一管理实战

IDEA多模块工程:Java与Python自动化测试框架统一管理实战

讲个真实场景。我接手某个自动化测试框架改造的时候,团队同时维护着两套代码:Java 这边用 TestNG 写接口用例已经跑了两三年,Python 那边用 pytest 处理数据校验和运维脚本也形成了规模。每次发布前,负责 Java 的同学跑完要导一份…

2026/10/21 5:01:00 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事:AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里,按宣传口径,本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”,而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起:用户到底在追求什么“封号重开”这四个字,放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流,背后是大量的时间和精力成本。正常情况下,没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”,而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时,就意识到:单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/21 4:27:17 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →