Python函数参数详解:形参与实参、位置与关键字参数及打散机制

沈亦白
沈亦白
发布时间:2026-10-16 | 5人浏览过
原创

本文深入解析Python函数参数体系,涵盖形参与实参的定义与区别,详细阐述不可变与可变类型在参数传递中的行为差异。重点讲解位置实参与关键字实参的传值规则、形参的六种分类及声明顺序,并深入剖析*与**打散机制在处理单列与双列容器时的具体应用。

一、函数参数的分类

在Python中,函数的参数主要划分为两类:形参(形式参数)与实参(实际参数)。

形参是指在定义函数时,在函数声明括号内列出的变量名。如果在调用函数时未向形参传入具体的实参,那么这些形参在当前的函数调用中就不具备实际的数据意义。

实参是指在调用函数时,真正传递给函数的具体值或变量。实参拥有具体的数据类型和实际内存地址,是函数执行过程中真正参与运算的数据。

举例:

def fn(n1,n2):  # 在此过程中定义的参数就是形参
    print(n1 + n2)
fn(10,20)  # 在此过程中传入的变量就是实参

二、形参是对实参的值拷贝

需要注意的是,形参和实参即使使用相同的变量名,它们在内存中也是两个独立的变量,互不影响。

举例:

def fn(num1):
    print(num1)
    num1 = 20
    print(num1)
num1 = 10
fn(num1)
print(num1)

对于不可变类型:

参考上例,当在函数内部对 num1 进行重新赋值时,外部再次打印 num1 仍显示原始值。这是因为在函数内部,形参 num1 重新指向了一个新的内存地址(重指向),而外部的实参 num1 依然指向原来的内存地址,其值并未发生改变。

对于可变类型:

参考上例,若 num1 为可变类型(如列表),在函数内部使用 append() 方法添加元素后,在函数外部打印 num1 会显示添加后的列表。这是因为对于可变对象,函数内部的操作直接修改了对象内容,没有进行重指向,此时实参与形参指向的是同一个内存ID。

三、实参的分类

实参在传递时主要分为两种形式:位置实参和关键字实参。

位置实参 —> 根据参数在函数定义中的位置顺序进行传递。

举例:

#Python学习交流:711312441
def fn(a,b,c):
    print(a)
    print(b)
    print(c)
fn(1,2,3)

如上例所示,传入参数时是严格按照参数定义的位置顺序进行匹配的。如果改变实参传入的顺序,传递给形参的值也会随之改变,这种依赖位置传递参数的形式称为位置实参。

 fn(a=1,b=2,c=3)

如果在调用函数时,通过“参数名=值”的方式指名道姓地传入参数,那么无论实参在调用语句中的位置如何变化,形参接收到的值都不会受到影响。这种形式的实参被称为关键字实参。

注:

1、位置实参必须严格按照定义时的顺序进行传递。如果调用时实参的顺序发生变化,形参接收到的值也会发生相应变化。

2、关键字实参采用“指名道姓”的赋值方式,因此即使改变实参在调用语句中的位置,也不会影响形参接收到的值。

3、在混合使用位置实参和关键字实参时,必须遵循“位置参数在前,关键字参数在后”的原则。即先进行位置参数的传值,再进行关键字实参的传值。

四、形参的分类

形参在定义时可以分为六种类型:

  • 带有默认值的位置形参
  • 不带默认值的位置形参
  • 带有默认值的关键字形参
  • 不带默认值的关键字形参
  • 可变长度的位置形参
  • 可变长度的关键字形参

实例:

def fn(a,b,c=10,*,d,e=20,**kwargs)

1、带及不带默认值的位置形参

在实例中,* 号之前的参数统称为位置形参。位置形参既可以通过位置实参传值,也可以通过关键字实参传值。

不带默认值的位置形参:

  • 不带有默认值的位置形参必须接收实参传值。如果在调用函数时未提供对应的实参,程序将报错。

带有默认值的位置形参:

  • 带有默认值的位置形参既可以使用实参进行传值,也可以不使用实参。当不使用实参传值时,系统将使用定义的默认值作为该形参的值。

2、带有及不带默认值的关键字形参

在实例中,* 号之后的参数均为关键字形参。在使用关键字形参时,必须使用关键字实参进行传值,否则程序会报错。

不带默认值的关键字形参:

  • 不带有默认值的关键字形参必须使用关键字实参进行传值。如果不传参数,程序将报错。

带有默认值的关键字形参:

  • 带有默认值的关键字形参既可以使用关键字实参进行传值,也可以不传值。当不传值时,系统将使用默认值作为其值。

3、可变长度的形参

可变长度位置形参:

  • 其位置通常位于普通位置形参和关键字形参之间。当传入的位置实参数量多于定义的位置形参时,多出的位置实参会被打包存储在可变长度的位置形参中。
  • 可变长度的关键字形参在例子中由 * 表示,只是给这个形参添加了一个名字。这个名字可以自定义,但约定俗成的命名为 *args。

可变长度的关键字形参:

  • 可变长度的关键字形参位于参数列表的末尾。当传入的关键字实参多于定义的关键字形参时,多出的部分会被存储在可变长度的关键字形参中,并以元组形式存储。
  • 可变长度的关键字形参使用 ** 进行表示。此时也需要给关键字形参添加一个名字,这个名字可以自定义,但约定俗成的称为 **kwargs,并以字典形式存储。

形参声明时,其声明顺序是有严格规定的,顺序为:

无默认值位置形参 --> 有关键字位置形参 --> 可变长度的位置形参 --> 无默认值的关键字形参 --> 有默认值的关键字形参 --> 可变长度的关键字形参

常用的参数列表类型:

-- (*args,**kwargs)

-- (a,*args)
-- (a,b=10,**kwargs)
        
-- (a,*,b,**kwargs)
-- (a,*args,b,**kwargs)

在使用形参时,建议按照位置进行传参。即使存在关键字参数,也尽量优先按位置传参,这样代码逻辑更加清晰易读。

五、打散机制

在使用可变长形参时,如果传入的值多于需要的值,多余的参数会进入可变长位置形参及可变长关键字形参。但如果直接传入一个元组或字典,如何将其直接解包变为元组及字典呢?

此时需要使用 * 及 ** 的打散机制。

* 用于打散单列容器(如列表、元组)。

** 用于打散双列容器(如字典)。

print(*(a,b,c))  --->  (a b c)
print(**{a:1,b:2})  ---> {a:1,b:2}

附:

在进行字符串字母的比较时,是根据字母在ASCII码表中对应的数值进行比较的,系统会遍历比较每个字符。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表