Python深入理解*和**含义和应用

news/2024/10/13 0:33:00

本文源代码:https://gitee.com/obullxl/PythonCS/tree/master/CS-CY2405

Python中*和**很常见

禅师在阅读Python代码过程中,经常看到一个函数或方法的入参是*args**kwargs(如:def func(*args, **kwargs)等)形式,或者在调用函数或方法时,在入参的元组和列表前面增加1个*号(如:func(*(1, 2, 3))等),或者在字典类型入参前面增加2个*号(如:func(**{'x':1, 'y':2, 'z':3})等)。

刚开始看到参数前面*号,禅师一度以为是C/C++中的指针,但在万物皆对象的Python种,指针是不会存在的。本文我们一起来看看1个*号和2个**号的含义和用法,也让我们来感受一下Python灵活性有多强大。

位置参数和命名参数

在了解函数入参*args**kwargs之前,我们首先要了解一下函数或方法的位置参数和命名参数,以函数定义def func(a, b, c, x=None, y=None, z=None)为例:

  • 位置参数通俗的讲就是参数的位置的固定的,与函数或方法的参数名无关,比如函数或方法的第1个参数、第2个参数等。样例函数的a/b/c入参就是位置参数,他们分别在函数的第1到第3个参数。Python语法规定,位置参数只能在函数或方法前面的参数(即中间不能有位置参数)。

  • 命名参数通俗的讲就是参数是有名字,在调用函数或方法时,需要指定参数的名称,命名参数可以有默认值。样例函数的x/y/z入参就是命名参数,x/y/z就是参数的名称,且他们均有None默认值。Python语法规定,位置参数只能在函数或方法后面的参数(即中间不能有位置参数)。

1个*和2个**的作用

其实从函数入参能看出来,1个*是位置参数,2个**是命名参数,那么它们到底有什么作用呢:

  • 函数或方法的定义,如def func(*args, **kwargs)1个*的作用是收集调用本函数的所有的位置参数,收集后的类型是元组;2个**的作用也是参数收集,只是收集的是命名参数,收集后的结果是字典(在Java中称为Map)。

  • 函数或方法的调用,如func(*(1, 2, 3), **{x=4, y=5, z=6}):*的作用是拆解,与收集相反;其中,1个*为把元组或列表按照顺序拆开,作为位置入参,2个**则把字典按照命名参数拆开。

例:定义函数或方法(参数收集)

def mfunc(*args, **kwargs):'''函数定义:收集参数,*把所有的位置参数收集到一个元组中,**则把最后的命名参数组装成Map字典。'''print(f'{type(args)} args = {args}')print(f'{type(kwargs)}  kwargs = {kwargs}')mfunc()
mfunc(1, 2, 3, x='a', y='b')
mfunc(1, 2, ('t1', 't2'), ['t1', 't2'], {'k1': 'v1', 'k2': 'v2'}, x='a', y='b')'''
入参拆解参数,定义收集参数,相互抵消,无实际意义。
'''
mfunc(*(1, 2, 3), **{'k1': 'v1', 'k2': 'v2'})

例:调用函数或方法(拆解或映射)

def mprint(x, y):'''函数调用:拆解参数,*把元组或列表按照顺序拆开,作为入参,**则把Map字典按照命名参数拆开。'''print(f'{type(x)} x = {x}')print(f'{type(y)} y = {y}')mprint(*(1, 2))
mprint(*((1, 2), 3))
mprint(**{'x': 'x1', 'y': 'y1'})

特别注意:拆解位置参数数量需要与函数或方式定义一致,或者拆解命名参数的参数名需要与定义一致!

禅定:Python为什么需要*和**?

从前面的分析可以看出***的作用和用法,Python中它们是必须的吗?禅师答案:

  • 函数和方法定义中是必须的:举个反射的简单场景,函数入参的个数、类型是动态的,因此需要收集(如:Java中为Object[]数组)

函数和方法调用是可选的,目的是为了简化编程(Python之禅:Beautifulis better than ugly.),不需要手工逐个参数设置,如调用函数入参func(*my_lsit, **my_dict)就明显比func(my_list[0], my_list[1], my_list[2], my_dict['x'], my_dict['y'], my_dict['z'])优雅太多了。


我的本博客原地址:https://ntopic.cn/p/2024050201


微信公众号:Python禅师

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/27164.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

设置border后,子元素和父容器存在间隙

下方也出现了间隙网上找了一圈,全是说inline-block的,但是我调整a标签为block还是有间隙。 问题代码 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=…

python教程3.1:数据类型:字符串+列表list

一、字符串 字符串是⼀个有序的字符的集合,⽤于在计算机⾥存储和表示⽂本信息 常用操作二、列表list []内以逗号分隔,按照索引,存放各种数据类型,每个位置代表⼀个元素 特征 1、增加操作追加,数据会追加到尾部 2、删除操作3、修改操作 4、查找操作 如果不知道元素在列表哪…

WPF上位机 - 轴运动控制

最近学习WPF,写了一个WPF上位机使用S7.NETPlus 库与西门子1500TPLC,控制西门子伺服的通用上位机界面。分享在写上位机过程中踩的一些坑和使用体验。 上位机介绍可以看到上位机分为3个区域轴选择,使能区域 控制参数设置区域 诊断区域选择使能区域 选择区域读取TIA中组态的轴工…

系统管理之Linux启动流程

1.系统初始化进程SysV风格: init centos5 配置文件:/etc/inittabUpstart风格: init centos6 配置文件:/etc/init.d/,/etc/inittabSystemd风格: systemd centos7 配置文件:/usr/lib/systemd/system/,/etc/systemd/system/ systemctl是一个systemd管理工具2.Systemd 服务…

提高安全性,优雅实现拷贝与交换:C++中的Copy-and-Swap惯用法

概述:拷贝并交换(Copy-and-Swap)是C++编程中的惯用法,用于实现赋值操作符和确保异常安全的拷贝构造函数。其核心思想是通过拷贝构造函数创建临时副本,再通过交换确保操作的异常安全性。这种方法在C++11之前和之后都适用,但在C++11中,移动语义和右值引用的引入使得实现可…

【排课小工具】排课程序设计与实现

本文记录了排课小工具的程序设计与实现过程,值得一提的是,在程序设计的过程中我几乎没有用到上一篇文章提到的有关领域模型的东西,而是大量沿用了原型软件的诸多设计,或许这个一工具并不适合面向对象的分析方式,更多的,我觉得还是自己对这一领域的认识太过肤浅,缺乏开发…

Linux下ffmpeg库的编译链接

Linux下ffmpeg库的链接。/usr/bin/ld: /usr/local/ffmpeg/lib/libavformat.a(aviobuf.o): in function `ff_crc04C11DB7_update:/home/ann/FFmpeg/ffmpeg/libavformat/aviobuf.c:568: undefined reference to `av_crc_get_table/usr/bin/ld: /home/ann/FFmpeg/ffmpeg/libavform…

【未整合】数学 day2.2

概率论 在 OI 中,认为概率是事件的固有属性。 将事件的集合称为概率空间。 用 \(\omega\) 表示事件。 认为随机变量 \(X,Y\) 独立,当且仅当 \(P(X=x\text{ 且 }Y=y)=P(X=x)\times P(Y=y)\) 恒成立。 两者互为充要。 令 \(P(A|B)\) 代表在 \(B\) 发生的条件下 \(A\) 发生的概率…