关于Python中*args和**kwargs的深入理解


Posted in Python onAugust 07, 2021

1. 理解  *  和  **

Python的赋值语句可以解包将可迭代元素剥离出来

In [6]: a, b, c = [1, 2, 3]
In [7]: a
Out[7]: 1
In [8]: b
Out[8]: 2
In [9]: c
Out[9]: 3

赋值语句可以理解为 a, b, c = [a, b, c] = [1, 2, 3], 将变量a, b, c与目标列表中的数据进行对应.

Python中 * 和 ** 可以理解成一个特殊的解包语法. 将可迭代的对象列表字典等, 获取其中的内容.

关于Python中*args和**kwargs的深入理解

将 * 应用到赋值语句中, 可以解包多个数据对应到一个列表变量.

In [10]: a, *other = [1, 2, 3, 4]
In [11]: a
Out[11]: 1
In [12]: other
Out[12]: [2, 3, 4]
 
In [13]: a, *middle, x = [1, 2, 3, 4]
In [14]: middle
Out[14]: [2, 3]

结合 print 函数理解解包, 第二个print(*['a', 'b', 'c', 'd']) 使用*号将列表解包后, 相当于print('a', 'b', 'c', 'd')

In [15]: print(['a', 'b', 'c', 'd'])
['a', 'b', 'c', 'd']
 
In [16]: print(*['a', 'b', 'c', 'd'])
a b c d

 2.Python函数的参数

Python函数的传参, 支持两种方式, 一种是基于位置传递(Positional Arguments), 一种是基于变量名称传递(Keyword Arguments).

比如定义一个函数func 接受4个参数

In [1]: def func(a, b, c, d):
   ...:    print(a, b, c, d)

可以基于位置传参, (1, 2, 3, 4)根据位置顺序分别赋值给参数a, b, c, d.

In [2]: func(1, 2, 3, 4)
1 2 3 4

也可以基于变量名传递参数, 指定(d=1, c=2, b=3, a=4)分别赋值给对应变量, keyword argument可以乱序

In [3]: func(d=1, c=2, b=3, a=4)
4 3 2 1

或者混合两种参数格式, 组合位置参数和关键字参数. 注意这时不能重复赋值, 即已经传递了位置参数, 不能再通过关键字传参.

In [4]: func(1, 2, d=3, c=4)
1 2 4 3
 
In [5]: func(1, 2, a=3, c=4)
TypeError: func() got multiple values for argument 'a'

 3. 支持任意参数的函数 *args, **kwargs

然后就是我们查看源码时经常看到的语法, *args, **kwargs. 可以看到arg和kwarg即是一个变量, 目的是保存函数中的位置参数和关键字参数,成一个元组和字段对象, 保存args和kwargs就是变量名.

In [1]: def func(var, *args, key=None, **kwargs):
   ...:     print('args: ', args)
   ...:     print('kwargs: ', kwargs)

定义一个除了位置参数 var , 和关键字参数 key 之外还接受任意参数的函数.

调用函数时,传的其他参数就会赋值给 args, 和 kwargs.

In [2]: func('one', 'two', 'three', key='key', four=4, five=5,)
args:  ('two', 'three')
kwargs:  {'four': 4, 'five': 5}
 
In [3]: func('one', 'two', key='key', three='three', four=4, five=5,)
args:  ('two',)
kwargs:  {'three': 'three', 'four': 4, 'five': 5}

可以看到 'one' 赋值给了变量 var,  'two' 和 'three' 传给了元组args,   'key'赋值给了变量 four=4, five=5, 传递给了kwargs , {'four': 4, 'five': 5}.

改变three的传参方式使用three='three'之后, three也去了kwargs.

4. 固定位置参数和关键字参数  /   * 

 Python3.8 中增加了固定参数的关键字 / 和 * , 使用/之前的参数,只能通过位置方式传参, 使用*之后的参数, 只能通过关键字方式传参.

重新写一个最开始的函数

In [1]: def func(a, /, b, *, c, d):
   ...:    print(a, b, c, d)

其中参数a只能通过位置传递, c和d只能通过关键字传递, 参数b不做限制

In [2]: func(1, 2, c=3, d=4)
1 2 3 4
In [3]: func(1, b=2, c=3, d=4)
1 2 3 4
 
In [4]: func(a=1, b=2, c=3, d=4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() got some positional-only arguments passed as keyword arguments: 'a'
 
In [5]: func(1, 2, 3, d=4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() takes 2 positional arguments but 3 positional arguments (and 1 keyword-only argument) were given

可以看到, 限制了参数类型之后, 传参方式错误函数会报TypeError, 应用到一些需要限制显式传递参数的场景, 可以提高代码的可读性.

5. **的另一个用法, 字典合并

3.8之后还增加了一个**的新用法, 支持在字典初始化时使用**语法. 合并现有字典的数据时, 可不使用dict.update()函数. 代码示例如下

In [1]: a = {'k': 1, 'm': 2}
In [2]: y = {'y': '3', 'z': 'ii'}
 
In [3]: {**a}
Out[3]: {'k': 1, 'm': 2}
In [4]: {**a, **y}
Out[4]: {'k': 1, 'm': 2, 'y': '3', 'z': 'ii'}
In [5]: {**a, **y, 'uu': 88}
Out[5]: {'k': 1, 'm': 2, 'y': '3', 'z': 'ii', 'uu': 88}

总结:

本文总结了python中*和**的使用方法,  解包时可以获取可迭代对象中的内容.

  1. * 和**在定义函数时使用, 使得函数可以支持任意长度的参数
  2. 解包时可将任意长度数据赋值给一个对象
  3. 关键字 / 和 * 规定参数的传递方式.
  4. 生成新的字典时使用**解包其他字典中的值

到此这篇关于Python中*args和**kwargs深入理解的文章就介绍到这了,更多相关Python中*args和**kwargs内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python中使用OpenCV进行人脸检测的例子
Apr 18 Python
Python Web框架Flask中使用新浪SAE云存储实例
Feb 08 Python
Python实现获取域名所用服务器的真实IP
Oct 25 Python
CentOS 7下安装Python 3.5并与Python2.7兼容并存详解
Jul 07 Python
Python登录并获取CSDN博客所有文章列表代码实例
Dec 28 Python
Python数据结构之双向链表的定义与使用方法示例
Jan 16 Python
python在非root权限下的安装方法
Jan 23 Python
Random 在 Python 中的使用方法
Aug 09 Python
Python使用PyQt5/PySide2编写一个极简的音乐播放器功能
Feb 07 Python
PyCharm中配置PySide2的图文教程
Jun 18 Python
python实现从ftp上下载文件的实例方法
Jul 19 Python
pytorch 预训练模型读取修改相关参数的填坑问题
Jun 05 Python
python3操作redis实现List列表实例
Aug 04 #Python
Python pandas求方差和标准差的方法实例
Aug 04 #Python
pandas求平均数和中位数的方法实例
Aug 04 #Python
Python NumPy灰度图像的压缩原理讲解
Aug 04 #Python
Python内置数据结构列表与元组示例详解
Python制作动态字符画的源码
Aug 04 #Python
Python进行区间取值案例讲解
Aug 02 #Python
You might like
SONY SRF-M100的电路分析
2021/03/02 无线电
php并发对MYSQL造成压力的解决方法
2013/02/21 PHP
解析PHP SPL标准库的用法(遍历目录,查找固定条件的文件)
2013/06/18 PHP
php计划任务之验证是否有多个进程调用同一个job的方法
2015/12/07 PHP
php安装ssh2扩展的方法【Linux平台】
2016/07/20 PHP
基于Jquery的动态添加控件并取值的实现代码
2010/09/24 Javascript
setInterval与clearInterval的使用示例代码
2014/01/28 Javascript
JS清空多文本框、文本域示例代码
2014/02/24 Javascript
Jqgrid之强大的表格插件应用
2015/12/02 Javascript
JavaScript实现同一个页面打开多张图片
2016/12/29 Javascript
JavaScript生成图形验证码
2020/08/24 Javascript
vue按需引入element Transfer 穿梭框
2017/09/30 Javascript
vue项目中公用footer组件底部位置的适配问题
2018/05/10 Javascript
vue解决使用webpack打包后keep-alive不生效的方法
2018/09/01 Javascript
js实现简单放大镜效果
2020/03/07 Javascript
JavaScript如何判断对象有某属性
2020/07/03 Javascript
举例讲解Python中字典的合并值相加与异或对比
2016/06/04 Python
利用Python爬取可用的代理IP
2016/08/18 Python
python中Apriori算法实现讲解
2017/12/10 Python
python 识别图片中的文字信息方法
2018/05/10 Python
python 画出使用分类器得到的决策边界
2019/08/21 Python
Python实现图片批量加入水印代码实例
2019/11/30 Python
python实现随机加减法生成器
2020/02/24 Python
Python jieba结巴分词原理及用法解析
2020/11/05 Python
香港迪士尼乐园酒店预订:Hong Kong Disneyland Hotels
2017/05/02 全球购物
全球领先的中国制造商品在线批发平台:DHgate
2020/01/28 全球购物
sealed修饰符是干什么的
2012/10/23 面试题
Windows和Linux动态库应用异同
2016/04/17 面试题
农贸市场管理制度
2014/01/31 职场文书
构建高效课堂实施方案
2014/03/13 职场文书
入党积极分子评语
2014/05/04 职场文书
创建文明城市标语
2014/06/16 职场文书
大专生求职信
2014/06/29 职场文书
儿童诗两首教学反思
2016/02/23 职场文书
市直属机关2016年主题党日活动总结
2016/04/05 职场文书
Python Matplotlib绘制等高线图与渐变色扇形图
2022/04/14 Python