在 Python 中,函数参数传递是编程的核心基础。Python 的参数传递机制与其他语言(如 C/C++)有所不同
2026/9/15 8:53:57 网站建设 项目流程

在 Python 中,函数参数传递是编程的核心基础。Python 的参数传递机制与其他语言(如 C/C++)有所不同,其本质是**“对象引用传递”**(Call by Sharing),即传递的是对象引用的拷贝,而非对象本身或单纯的引用。

为了让你全面掌握这一技术,本文将从参数传递的底层机制、多种传参形式、参数定义规范以及命令行参数传递等维度进行深度解析,并辅以详尽的代码案例。

一、 Python 参数传递的底层机制

在 Python 中,一切皆对象。变量本质上是指向对象的指针。因此,函数参数传递传递的是变量的值,也就是对象在内存中的地址。这种机制在实际表现上取决于对象的可变性:

  1. 不可变对象(如 int, float, str, tuple):在函数内部对参数的修改(如赋值、运算)会创建新对象并重新绑定局部变量,不会影响外部原对象。这在行为上类似于 C 语言的“值传递”。
  2. 可变对象(如 list, dict, set):在函数内部通过原地操作(如append,update)修改对象内容,会直接影响外部原对象。这在行为上类似于 C 语言的“引用传递”。
# 1. 不可变对象示例defchange_immutable(val):val=100# 重新赋值,创建新对象,不影响外部num=1change_immutable(num)print(num)# 输出: 1# 2. 可变对象示例defchange_mutable(lst):lst.append(100)# 原地修改,影响外部原对象my_list=[0]change_mutable(my_list)print(my_list)# 输出: [0, 100]

二、 五种基础传参形式

Python 提供了极其灵活的传参方式,主要包括以下五种:

1. 位置参数(Positional Arguments)

最基础的传参方式,实参的顺序和数量必须与形参一一对应。

defintroduce(name,age):print(f"姓名:{name}, 年龄:{age}")introduce("张三",25)# 正确# introduce("张三") # 报错:缺少参数
2. 关键字参数(Keyword Arguments)

通过参数名=值的形式传递,无需按顺序,代码可读性更强。注意:位置参数必须放在关键字参数前面

defintroduce(name,age):print(f"姓名:{name}, 年龄:{age}")introduce(age=25,name="张三")# 顺序随意introduce("张三",age=25)# 混合使用:位置在前,关键字在后# introduce(name="张三", 25) # 报错:关键字参数不能在位置参数前
3. 默认参数(Default Parameters)

定义时指定默认值,调用时可省略。默认参数必须位于非默认参数之后

⚠️经典大坑:默认参数千万不要使用可变对象(如 list, dict)。因为默认值只在函数定义时计算一次,多次调用会共享同一个对象,导致意外累加。正确做法是使用None并在函数内部初始化。

# ❌ 错误示范defbad_add_item(item,lst=[]):lst.append(item)returnlstprint(bad_add_item(1))# [1]print(bad_add_item(2))# [1, 2] 意外累加!# ✅ 正确示范defgood_add_item(item,lst=None):iflstisNone:lst=[]lst.append(item)returnlstprint(good_add_item(1))# [1]print(good_add_item(2))# [2] 符合预期
4. 可变位置参数(*args)

使用单星号*接收任意数量的位置参数,并将其打包成一个元组(tuple)

defcalc_sum(*nums):print(f"收到的参数类型:{type(nums)}")# <class 'tuple'>returnsum(nums)print(calc_sum(1,2,3))# 输出: 6print(calc_sum(10,20,30,40))# 输出: 100
5. 可变关键字参数(**kwargs)

使用双星号**接收任意数量的关键字参数,并将其打包成一个字典(dict)

defshow_profile(**info):print(f"收到的参数类型:{type(info)}")# <class 'dict'>forkey,valueininfo.items():print(f"{key}:{value}")show_profile(name="李四",age=30,city="北京")

三、 参数定义的完整顺序与高级特性

在复杂的函数设计中,我们常常需要组合使用上述参数。Python 对参数的定义顺序有严格的规范,必须遵守:
仅限位置参数 (/) → 标准位置参数 → 默认参数 → 可变位置参数 (*args) → 仅限关键字参数 (*) → 可变关键字参数 (**kwargs)

此外,Python 3.8+ 引入了/*作为分隔符,用于强制限定传参方式:

  • /左侧的参数只能通过位置传递,不能使用关键字。
  • *右侧的参数必须通过关键字传递。
defcomplex_func(a,b,/,c,d=10,*args,e,f=20,**kwargs):""" a, b: 仅限位置参数 c: 标准位置参数 d: 默认参数 *args: 可变位置参数 e: 仅限关键字参数 f: 仅限关键字默认参数 **kwargs: 可变关键字参数 """print(a,b,c,d,args,e,f,kwargs)# 合法调用complex_func(1,2,3,4,5,e=6,f=7,extra="test")# complex_func(a=1, b=2, c=3, e=6) # 报错:a和b不能关键字传参# complex_func(1, 2, 3, 4, 5, 6) # 报错:e必须关键字传参
参数解包技术

在调用函数时,星号同样具备“解包”功能。*可将列表/元组解包为位置参数,**可将字典解包为关键字参数。

defmultiply(x,y,z):returnx*y*z nums=[2,3,4]print(multiply(*nums))# 等价于 multiply(2, 3, 4),输出: 24info={"x":2,"y":3,"z":4}print(multiply(**info))# 等价于 multiply(x=2, y=3, z=4),输出: 24

四、 命令行参数传递技术

除了函数内部的参数传递,在编写 Python 脚本(CLI 工具)时,我们还需要接收来自终端的命令行参数。Python 标准库提供了argparse模块,第三方库click则提供了更优雅的装饰器语法。

1. 使用 argparse(标准库)
importargparsedefsay_hello(name):print(f"Hello{name}!")if__name__=="__main__":parser=argparse.ArgumentParser(description="命令行问候工具")parser.add_argument("--name","-n",help="你的名字",default="World")args=parser.parse_args()say_hello(args.name)# 终端运行: python script.py --name Alice# 输出: Hello Alice!
2. 使用 click(第三方库)
importclick@click.command()@click.option("--name","-n",default="World",help="你的名字")defsay_hello(name):print(f"Hello{name}!")if__name__=="__main__":say_hello()

总结

Python 的参数传递技术建立在“对象引用传递”的底层逻辑之上。在实际开发中,熟练掌握位置参数、关键字参数、默认参数以及*args**kwargs的组合使用,能够让你的函数接口设计得更加灵活、健壮且易于扩展。同时,务必警惕可变默认参数的陷阱,并善用参数解包和命令行参数解析工具,以提升代码的工程化水平。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询