关于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入门之语句(if语句、while语句、for语句)
Jan 19 Python
Python实现全角半角字符互转的方法
Nov 28 Python
Python部署web开发程序的几种方法
May 05 Python
Python 实现数据库(SQL)更新脚本的生成方法
Jul 09 Python
python 垃圾收集机制的实例详解
Aug 20 Python
Python爬取商家联系电话以及各种数据的方法
Nov 10 Python
python3实现网络爬虫之BeautifulSoup使用详解
Dec 19 Python
python实现复制文件到指定目录
Oct 16 Python
详解python中eval函数的作用
Oct 22 Python
Python使用微信接入图灵机器人过程解析
Nov 04 Python
解决python replace函数替换无效问题
Jan 18 Python
使用python编写一个语音朗读闹钟功能的示例代码
Jul 14 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
PHP购物车类Cart.class.php定义与用法示例
2016/07/20 PHP
用PHP做了一个领取优惠券活动的示例代码
2019/07/05 PHP
Yii框架响应组件用法实例分析
2019/09/04 PHP
Yii框架的redis命令使用方法简单示例
2019/10/15 PHP
js表数据排序 sort table data
2009/02/18 Javascript
Jquery遍历节点的方法小集
2014/01/22 Javascript
如何让你的Lightbox支持滚轮缩放及Base64图片
2014/12/04 Javascript
总结JavaScript中布尔操作符||与&amp;&amp;的使用技巧
2015/11/17 Javascript
KnockoutJs快速入门教程
2016/05/16 Javascript
深入浅析JavaScript中的Function类型
2016/07/09 Javascript
JS前端开发判断是否是手机端并跳转操作(小结)
2017/02/05 Javascript
详解vue表单验证组件 v-verify-plugin
2017/04/19 Javascript
Vue2实时监听表单变化的示例讲解
2018/08/30 Javascript
node.js之基础加密算法模块crypto详解
2018/09/11 Javascript
三种Webpack打包方式(小结)
2018/09/19 Javascript
基于elementUI使用v-model实现经纬度输入的vue组件
2019/05/12 Javascript
vue3.0中setup使用(两种用法)
2020/12/02 Vue.js
JavaScript实现点击切换验证码及校验
2021/01/10 Javascript
python实现360皮肤按钮控件示例
2014/02/21 Python
Python编程中对super函数的正确理解和用法解析
2016/07/02 Python
Python基础学习之类与实例基本用法与注意事项详解
2019/06/17 Python
Python 日期时间datetime 加一天,减一天,加减一小时一分钟,加减一年
2020/04/16 Python
Python应用实现双指数函数及拟合代码实例
2020/06/19 Python
python 实现ping测试延迟的两种方法
2020/12/10 Python
世界上最大的在线旅行社新加坡网站:Expedia新加坡
2016/08/25 全球购物
英国在线房屋中介网站:Yopa
2018/01/09 全球购物
世界汽车零件:World Car Parts
2019/09/04 全球购物
历史学专业个人的自我评价
2013/10/13 职场文书
施工资料员的岗位职责
2013/12/22 职场文书
加拿大留学自荐信
2014/01/28 职场文书
报告会主持词
2014/04/02 职场文书
第二课堂活动总结
2014/05/07 职场文书
演讲开头怎么书写?
2019/08/06 职场文书
帮你提高开发效率的JavaScript20个技巧
2021/06/18 Javascript
HTML5 语义化标签(移动端必备)
2021/08/23 HTML / CSS
Spring boot实现上传文件到本地服务器
2022/08/14 Java/Android