Python 不同参数类型的使用

位置参数

顾名思义,在调用函数时根据函数定义的参数位置来传递参数

def fun(a,b):
    print("arg a:", a)
    print("arg b:", b)

fun(10,20)
# arg a: 10
# arg b: 20

在使用位置参数进行参数传递时,要保证参数数目和顺序对应,不然会报错。

关键字参数

在调用函数时,也可以通过 “键-值” 对来对应赋值,这样不用参数间的顺序问题,同时程序也更明了。

def fun(a,b):
    print("arg a:", a)
    print("arg b:", b)

fun(a = 10,b = 20)
# arg a: 10
# arg b: 20

fun(b = 10,a = 20)
# arg a: 20
# arg b: 10

fun(10,b = 20)
# arg a: 10
# arg b: 20

fun(10,a = 20)
# TypeError: fun() got multiple values for argument 'a'

fun(a = 10,20)
# SyntaxError: positional argument follows keyword argument

根据上面程序提示,可以得知:

根据关键字赋值时不区分先后顺序。

在单个函数调用时,不能同时给单个参数赋多个值。

位置参数和关键字参数同时存在时,位置参数应该在关键字参数之前。

默认参数

默认参数是在函数定义的时候已经给某些参数赋值,即为默认值。默认赋值的参数即为默认参数,在对应参数有参数传递时要重新赋值,没有参数传递时即为默认值。

def fun(a,b,c = 30):
    print("arg a:", a)
    print("arg b:", b)
    print("arg c:", c)

fun(10,20)
# arg a: 10
# arg b: 20
# arg c: 30

fun(10,20,40)
# arg a: 10
# arg b: 20
# arg c: 40

fun(10,b = 20,c = 40)
# arg a: 10
# arg b: 20
# arg c: 40

fun(a = 10,b = 20,c = 40)
# arg a: 10
# arg b: 20
# arg c: 40

fun(b = 10,c = 20,a = 40)
# arg a: 40
# arg b: 10
# arg c: 20

再看一种情况:

def fun(a,c = 30,b):
    print("arg a:", a)
    print("arg b:", b)
    print("arg c:", c)

# SyntaxError: non-default argument follows default argument

可知,不管是在函数定义或者函数调用中,用 = 赋值的参数都应该在不用 = 赋值的参数之后,即位置参数在关键字参数之前。

可变长度参数

在实际编程中,有时我们希望给函数传递不同数量的参数,或者在函数定义中直接设置可变长度的参数,这就是可变长度参数。变长参数在函数中的声明不是显式命名的,因为参数数目在运行之前是未知的,参数的个数取决于运行时实际传递的参数个数。

可变长度参数主要是靠包裹(packing)位置参数或者包裹关键字参数实现的。

非关键字可变长参数(元组)

当函数调用的时候,所有的形参(必须的和默认的)都将值赋给了在函数声明中相对应的局部变量,剩下的非关键字参数可以按照顺序插入到一个元组中便于访问。

def fun(a,*args):
    print("arg a:", a)
    for i in args:
        print("*args:", i)

fun(10,20,30,40)
# arg a: 10
# *args: 20
# *args: 30
# *args: 40

fun(a = 10,20,30,40)
# SyntaxError: positional argument follows keyword argument

fun(20,30,40,a = 10)
# TypeError: fun() got multiple values for argument 'a'

同样的,在参数调用也需要保证,位置参数在关键字参数之前,不能重复赋值。

* 操作符之后的形参将作为元组传递给函数,元组保存了参数 arg 之后所有传递给函数的参数。如果没有,则为空。另外 * 后边只是表示元组的名称,并不一定要用 args 来表示,任何一个变量都行。只是 * 是必需的。

关键字变量参数(字典)

同样对于含有关键字的参数来说,可以用变量参数字典来处理这种情况。

def fun(a,**kwargs):
    print("arg a:", a)
    for key, value in kwargs.items():
        print("**kwargs:", key, "=", value)

fun(10,b = 20,c = 30,d = 40)
# arg a: 10
# **kwargs: b = 20
# **kwargs: c = 30
# **kwargs: d = 40

fun(b = 20,c = 30,d = 40,a = 10)
# arg a: 10
# **kwargs: b = 20
# **kwargs: c = 30
# **kwargs: d = 40

fun(b = 20,c = 30,d = 40,10)
# SyntaxError: positional argument follows keyword argument

上面的程序说明,在保证位置参数有变量输入的情况下,**kwargs 会把剩下的关键字参数组合成字典,而不关心关键字参数的顺序。但仍要保证位置参数在关键字参数之前。

为了区分关键字参数和非关键字参数,在关键字参数前会有 ** 作为区别。同样 ** 后边只是表示字典的名称,并不一定要用 kwargs 来表示,而是任何一个都可以。只是 ** 是必需的。

解包裹参数

上面我们利用 *(元组)和 **(字典)实现了函数定义,实际上,在函数定义的时候,也可以使用 * 和 **,这种操作叫做解包裹(unpacking)。

* 解包裹

def fun(a,b,c):
    print("arg a:", a)
    print("arg b:", b)
    print("arg c:", c)

arg = (10,20)
fun(30,*arg)
# arg a: 30
# arg b: 10
# arg c: 20

fun(*arg,30)
# arg a: 10
# arg b: 20
# arg c: 30

元组解包时,就地展开,元组中的一个元素对应一个位置参数。因此在使用过程中要注意赋值的顺序,一一对应。

** 解包裹

def fun(a,b,c):
    print("arg a:", a)
    print("arg b:", b)
    print("arg c:", c)

kwargs = {'a':10,'b':20}
fun(c = 30,**kwargs)
# arg a: 10
# arg b: 20
# arg c: 30

fun(**kwargs,30)
# SyntaxError: positional argument follows keyword argument unpacking

字典解包时,就地展开,如果都是关键字参数,便不用在意顺序。

由于字典解包裹时,相当于关键字参数赋值,因此位置参数不能放置在 **kwargs 后边。

大乱斗——位置参数、默认参数、可变参数的混合

使用时的基本原则是:位置参数、默认参数、* 包裹、** 包裹按顺序排列(定义和调用都保证这个顺序)

def fun(a, b, c=30, d=40, *args, **kwargs):
    print("arg a:", a)
    print("arg b:", b)
    print("arg c:", c)
    print("arg d:", d)
    for i in args:
        print("*args:", i)
    for key, value in kwargs.items():
        print("**kwargs:", key, ",", value)

fun(10,20,50,60,70,80,90,e = 100,f = 110,g = 120)
# arg a: 10
# arg b: 20
# arg c: 50
# arg d: 60
# *args: 70
# *args: 80
# *args: 90
# **kwargs: e , 100
# **kwargs: f , 110
# **kwargs: g , 120

从上面可以看出,*args 包裹只“收留”那些不带有关键字的参数,组成元组。而 **kwargs 只“收留”那些带有关键字的参数,组成字典。并且根据位置参数必须要在关键字参数之前的规则来看,*args 必须要在 **kwargs 之前

再看一个混合使用的例子:

def fun(a, b, *args, c=30, d=40, **kwargs):
    print("arg a:", a)
    print("arg b:", b)
    print("arg c:", c)
    print("arg d:", d)
    for i in args:
        print("*args:", i)
    for key, value in kwargs.items():
        print("**kwargs:", key, ",", value)

fun(10,20,50,60,70,80,90,e = 100,f = 110,g = 120)
# arg a: 10
# arg b: 20
# arg c: 30
# arg d: 40
# *args: 50
# *args: 60
# *args: 70
# *args: 80
# *args: 90
# **kwargs: e , 100
# **kwargs: f , 110
# **kwargs: g , 120

从上边可以看到,*args 可以位于 a,b 之后,这时因为*args 都是非关键字参数,而 a,b 也是非关键字参数,*args 之后是默认参数和关键字参数,符合之前强调的规则,因此正确运行。

假设把 *args 放在 a 和 b 之间,Python 便不能识别哪一部分是可变长度参数,哪一部分是位置参数,便会报错。

def fun(a, *args, b, c=30, d=40, **kwargs):
    print("arg a:", a)
    print("arg b:", b)
    print("arg c:", c)
    print("arg d:", d)
    for i in args:
        print("*args:", i)
    for key, value in kwargs.items():
        print("**kwargs:", key, ",", value)

fun(10,20,50,60,70,80,90,e = 100,f = 110,g = 120)
# TypeError: fun() missing 1 required keyword-only argument: 'b'

但是上面的程序如果我们想要给 c 和 d 赋值,又该如何处理,可以用关键字参数对 c 和 d 进行赋值或者将默认参数放置到 *args 前边进行赋值。

用关键字进行赋值

def fun(a, b, *args, c=30, d=40, **kwargs):
    print("arg a:", a)
    print("arg b:", b)
    print("arg c:", c)
    print("arg d:", d)
    for i in args:
        print("*args:", i)
    for key, value in kwargs.items():
        print("**kwargs:", key, ",", value)

fun(10,20,50,60,70,c = 80,d = 90,e = 100,f = 110,g = 120)
# arg a: 10
# arg b: 20
# arg c: 80
# arg d: 90
# *args: 50
# *args: 60
# *args: 70
# **kwargs: e , 100
# **kwargs: f , 110
# **kwargs: g , 120

 改变函数定义时参数的位置顺序

def fun(a, b, c=30, d=40, *args, **kwargs):
    print("arg a:", a)
    print("arg b:", b)
    print("arg c:", c)
    print("arg d:", d)
    for i in args:
        print("*args:", i)
    for key, value in kwargs.items():
        print("**kwargs:", key, ",", value)

fun(10,20,50,60,70,e = 100,f = 110,g = 120)
# arg a: 10
# arg b: 20
# arg c: 50
# arg d: 60
# *args: 70
# **kwargs: e , 100
# **kwargs: f , 110
# **kwargs: g , 120

再看一种情况:

def fun(a, b, *args, c=30):
    print("arg a:", a)
    print("arg b:", b)
    print("arg c:", c)
    for i in args:
        print("*args:", i)

fun(10,20,50,60,70,c =40)
# arg a: 10
# arg b: 20
# arg c: 40
# *args: 50
# *args: 60
# *args: 70

fun(10,20,50,60,70,40)
# arg a: 10
# arg b: 20
# arg c: 30
# *args: 50
# *args: 60
# *args: 70
# *args: 40

当默认参数变为最后时,是否使用关键字赋值结果是完全不同的,应该注意。

最后

位置参数要保证数目顺序一一对应

默认参数重新赋值时要注意参数位置

关键字参数一定在非关键字参数之后,不管是调用阶段还是定义阶段

关键字参数的顺序没有要求,保证数目对应即可。

使用可变长度参数时,要注意各个参数之间的排列顺序。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值