【python语法】*args和**kwargs的理解

*args 是打包和拆分为元组

args有两部分构成为——和args。这里的重点是
所以为了讲清楚
args,我们要追根溯源——理解*的作用。这里的args只是一个参数名称而已,可以用其他的替换,比如下面的示例中都使用number进行替换。

*的作用,有2个—— 打包参数(pack)和拆分参数(unpack)!

* 打包参数:

例1:

def foo(*number):
    print(number)


foo(1, 2, 3, 4, 5)

输出:

(1, 2, 3, 4, 5)

*把函数foo()接受到的多个参数1,2,3,4,5,打包成了元组(1,2,3,4,5),赋值给了形参number。
我们可以验证一下:
例2:

def foo(*number):
    for i in number:
        print(i)
    print(type(number))


foo(1, 2, 3, 4, 5)
1
2
3
4
5
<class 'tuple'>

从例2可以看出,number确实被赋予了(1,2,3,4,5)这个实参。
例3:

def foo(a, *number):
    print('a:', a)
    print('number:', number)
    for i in number:
        print(i)
    print(type(number))


foo(1, 2, 3, 4, 5)
a: 1
number (2, 3, 4, 5)
2
3
4
5
<class 'tuple'>

注意:

  • ∗的作用:函数接受实参时,按顺序分配给函数形参,如果遇到带∗的形参,那么就把还未分配出去的实参以元组形式打包(pack),分配给那个带 *的形参。

注意例4我特地找了个报错的例子。自己分析一下为啥会报错。答案是:c前面的参数带∗ *∗,把剩下的实参都接受走了,c没有传入实参!
例5:

def foo(a, b, *number, c):
    print('a:', a)
    print('b:', b)
    print('c:', c)
    print('number:', number)
    for i in number:
        print(i)
    print(type(number))


foo(1, 2, 3, 4, 5)
Traceback (most recent call last):
  File "C:/Users/PycharmProjects/untitled10/test19.py", line 11, in <module>
    foo(1, 2, 3, 4, 5)
TypeError: foo() missing 1 required keyword-only argument: 'c'

* 拆分参数

例6:

def bar(a,b,c):
    print(a,b,c)

bar(*[1,2,3])

1 2 3

可以看出, *这次没有用在函数定义中,而是用在了函数调用中。在本例中的作用是啥呢?
答案是:把打包了的实参(元组或列表),拆分(unpack)成单个的,依次赋值给函数的形参。
在本例中,打包了的实参[1,2,3]被拆分,1赋值给了形参a,2赋值给了形参b,3复制给了形参c。

再看看下面哪个示例可以正常运行?
例7:

def bar(a,b):
    print(a,b)


bar(*[1, 2, 3])

例8:

def bar(a, b, c, d):
    print(a, b, c, d)


bar(*[1, 2, 3])

例9:

def bar(a, b, c, d=10):
    print(a, b, c, d)


bar(*[1, 2, 3])

答案是只有例9可以正常运行。因为按照我们讲的原理,例7的实参3没有对应的形参接受,例8的形参d没有实参赋值。

**kwargs 是打包和拆分为字典

打包参数

上边*args学懂了**kwargs也就很容易明白了。
**kwargs也有两部分构成为——**和kwargs。这里的重点是∗ ∗ **∗∗。没错,kwargs仅仅是一个约定俗成的写法,没有其他特殊含义,换成其他的也照用不误,但是为了代码可读性,最好还是用约定俗成的。
**的作用同样也有两个—— 打包参数(pack)和拆分参数(unpack)!
但是区别还是有的,简单来说就是:
打包(pack):*args是把多个位置参数打包成元组,**kwargs是把多个关键字参数打包成字典。
拆分(unpack):*args是把打包了的参数拆成单个的,依次赋值给函数的形参,**kwargs是把字典的键值拆成单个的,依次赋值给函数的形参。

例10:

def bar(**number):
    print(number)


bar(a=1, b=2, c=3)
{'a': 1, 'b': 2, 'c': 3}

例11:

def bar(a, b, c):
    print(a,b,c)


bar(**{'a': 1, 'b': 2, 'c': 3})
1 2 3

注意这里有个需要注意的地方,就是用 **方式拆解字典给形参赋值时,需要字典的键名和函数形参一致,否则会报错,自己试试就知道了。

位置参数,关键字参数,*args,**kwargs混用是要有一定顺序的,这里我特地不写了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超好的小白

没体验过打赏,能让我体验一次吗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值