一、理论解释:

*参数与**参数是Python参数中的重点知识,他们都被称为可变参数(任意参数),我们经常会在代码中看到*args、**kwargs

作为函数定义时:收集未匹配参数组成tuple或dict对象

1、*参数收集所有未匹配的位置参数组成一个tuple对象,局部变量args指向此tuple对象

2、**参数收集所有未匹配的关键字参数组成一个dict对象,局部变量kwargs指向此dict对象

def temp(*args,**kwargs):pass

作为函数调用时:解包功能

1、*参数用于解包tuple对象的每个元素,作为一个一个的位置参数传入到函数中

2、**参数用于解包dict对象的每个元素,作为一个一个的关键字参数传入到函数中

my_tuple = ("wang","yuan","wai")temp(*my_tuple)
#---等同于---#
temp("wangyuan","yuan","wai")
my_dict = {"name":"wangyuanwai","age":32}temp(**my_dict)
#----等同于----#
temp(name="wangyuanwai",age=32)

二、   *args 例子

这些基本概念暂时不理解很正常,完全理解需要一个过程……接下来的几个 *args 例子会说明这些概念,希望可以对每一位学习Python的同学带来帮助!!

1)包含两个位置参数的函数print_str

def print_str(first, second):print(first)print(second)

只传1个参数调用print_str()函数,会发生什么呢?

In [31]: print_str("hello")TypeError: print_str() missing 1 required positional argument: 'second'

TypeError:解释器在控制台告知print_str()函数需要2个参数,而你只为print_str()函数传入了1个参数!

思考:怎么修改print_str()函数为即可接受一个参数、也可接受两个参数、甚者接受数量不定的更多参数呢?

2)修改print_str()函数可接受一个参数、也可接受数量不定的参数

将print_str()函数的最后一个参数修改为可变参数*second

def print_str(first, *second):print(first)print(second)

此时我们再传一个参数调用print_str()函数,看看这次发生什么?

In [34]: print_str("hello")
hello
()

这次不再报错,传入的第一个字符串参数"hello"打印出来了,没有传入参数的*second则打印的是一个tuple对象的字符串表示形式,即一个括号"()"  。 注意:()表示含有0个元素的tuple对象!

思考:为什么second变量变成一个tuple对象了?我们继续向下学习!

3)再做一个实验,为print_str()函数传入四个参数…会发生什么?

In [35]: print_str("hello","美女","小猫","青蛙")hello
('美女', '小猫', '青蛙')

第一个参数“hello”,正常打印在第一行……

第二个参数"美女",第三个参数“小猫”,第四个参数“青蛙”在函数的内部被组装进1个新的tuple对象中,而这个新的tuple对象会赋值给变量second,此时局部变量second指向了一个tuple对象

说明:函数调用时传入的参数,会按照从左到右的顺序依次在函数中使用,最左侧的参数先由位置参数first使用(匹配),剩下的所有未匹配的参数会被自动收集到1个新的tuple对象中,而局部变量second会指向这个新的tuple对象

注意:*参数只收集未匹配的位置参数

4)调用print_str()函数时,直接传入一个 *参数会发生什么?

def print_str(first, *second):print(first)print(second)

控制台调用:

In [38]: numbers_strings = ("1","2","3","4","5")...: print_str(*numbers_strings)  # 注意这里的*numbers_strings1
('2', '3', '4', '5')

说明:*numbers_strings出现在函数调用时,称为解包(一个“*”字符后面紧挨着1个tuple对象),numbers_strings自身是一个tuple对象,所以也称为元组的解包,tuple中的元素解包成一个一个的位置参数传入到函数中,所以才有下面两个语句的相等性!

print_str(*numbers_strings)

等同于

print_str("1","2","3","4","5")

5)未定义可变参数的函数被调用时,传入*参数会发生什么呢?

def print_str(first, second):print(first)print(second)

控制台调用:

In [40]: numbers_strings = ("1","2")...: print_str(*numbers_strings)1
2

print_str(*numbers_string)

等同于

print_str("1","2")

元组解包的过程中会将每一个元素依次放入到位置参数,这说明元组的解包功能的如下特点:

1、可以在可变参数中使用

2、也可以在未定义可变参数的函数上使用

元组解包功能是完全独立的一个功能

再次说明:*参数,出现在函数的不同的位置上时,具备不同的功能

1、当*参数出现在函数定义时,表示可变参数

2、当*参数出现在函数调用时,则表示解包功能

注意:解包tuple的时候,tuple的元素数量要与函数的位置参数总数一致

三、**kwargs例子

1)函数定义中,参数名称前有两个**

def printStr(**anything):print(anything)

传入两个关键字参数调用printStr函数,看看发生什么?

In [42]: printStr(first = 5, second = 100){'first': 5, 'second': 100}

打印结果为dict对象的字符串形式,为什么anything成为dict了?

说明:函数调用时,传入的关键字参数有匹配的位置参数时,则位置参数优先使用(匹配)这些关键字参数,剩余所有未使用(未匹配)的关键字参数会在函数内组装进一个dict对象中,组装后dict对象会赋值给变量名anything,此时局部变量anything指向一个dict对象

注意:**参数只收集未匹配的关键字参数

2)函数调用时使用字典解包功能(dict对象前加**)

def printStr(first, **dict):print(str(first) + "\n")print(dict)

控制台调用:

In [44]: printDic = {"name": "tyson", "age":"99"}...: printStr(100, **printDic)100{'name': 'tyson', 'age': '99'}#等同于In [45]: printDic = {"name": "tyson", "age":"99"}...: printStr(100, name = "tyson", age = "99") 100{'name': 'tyson', 'age': '99'}

说明:函数调用时,在一个dict对象的前面,添加**,表示字典的解包,它会把dict对象中的每个键值对元素,依次转换为一个一个的关键字参数传入到函数中。

四、总结

Python语法中,当*参数和**参数同时出现在函数定义的参数列表中时,说明参数列表可接受任意数量的参数,它们都统称为可变参数。

函数定义时

1、*args表示可接受任意个(包含0个)位置参数,当函数调用时,所有未使用(未匹配)的位置参数会在函数内自动组装进一个tuple对象中,此tuple对象会赋值给局部变量args

2、**kwargs表示可接受任意个(包含0个)关键字参数,当函数调用时,所有未使用(未匹配)的关键字参数会在函数内组装进一个dict对象中,此dict对象会赋值给局部变量kwargs

注意:函数定义时,二者同时存在,一定需要将*args放在**kwargs之前

函数调用时

1、*args表示解包元组对象中的每个元素作为位置参数传入到被调用函数中

2、**kwargs表示解包字典对象中的每个元素作为关键字参数传入到被调用函数中

注意事项
1、可变参数,可以传数量不定的多个参数,包括0个参数

2、可变参数,必须定义在普通参数(也称位置参数、必选参数、选中参数等名称)以及默认值参数的后面,这是因为可变参数会收集所有【未匹配】的参数,如果将可变参数定义在前面,那么普通参数与默认值参数就无法匹配到传入的参数,因为全都收集到可变参数中了。

def printStr(普通参数,默认值参数name="王员外",*参数,**参数):pass

3、*参数必须定义在**参数的前面

def printStr(普通参数,*参数,**参数):pass

4、调用包含*args参数的函数时,不要直接传入一个tuple对象,如果传入的是一个tuple对象,那么这个tuple对象只会成为未匹配的,函数内组装的tuple对象中一个元素而已。我们可以将tuple对象的元素使用元组解包语法传入,解包语法:*tuple。

temp = (1,2,3,4,5)def my_first(*args):print(args)my_first(temp)  #temp只算一个参数,除非你有这个需求my_first(*temp) #OK

5、调用包含**kwargs参数的函数时,不要直接传入一个字典对象,一个字典对象只算一个参数,此时会报错,因为一个dict对象不符合关键字参数的语法规范,字典对象可以使用字典解包语法,解包语法: **dict

my_book = {"first":"小当家", "seoncd": "我是baby"}def my_blood(**kwargs):print(kwargs)my_blood(my_book)   #作为一个字典对象传入my_blood(**my_book) #一个一个的关键字参数传入

6、*参数的变量名,一般使用变量名args,只是建议,你想叫啥名都行,它只是局部变量名

7、**参数的变量名,一般使用变量名kwargs,只是建议,你想叫啥名都行,它也是个局部变量名

一个包含位置参数、默认值参数,可变参数的函数(供参考)

def my_first_blood(first_name,last_name,age=0,*args,**kwargs):print(first_name)print(last_name)print(age)for ele in args:print(ele)for key,value in kwargs.items():print(key)print(value) 

调用方式:

n [47]: my_first_blood("王", "员外")王
员外
0In [48]: ...: my_first_blood("王", "员外", 32)王
员外
32In [49]: my_first_blood("王", "员外", 32, "北京", "海淀", style="开心")王
员外
32
北京
海淀
style
开心

一个仅传入关键字参数,导致报错的函数

def temp(say, **kwargs):print(say)print(kwargs)temp(fk=100, hello=1000)

由于位置参数say,与传入的关键字参数fk和hello均不能匹配,所以此调用会导致报错。关键字参数必须得与位置参数的名称相匹配时,才能被位置参数使用.如下改变,即可:

In [52]: temp(10,fk=100, hello=1000)10
{'fk': 100, 'hello': 1000}

解包功能不只是tuple、还有list、str、range

first = (1,2,3)second = [1,2,3]third = "123"fourth = range(4)print(*first)print(*second)print(*third)print(*fourth)

五、再用例子系统说明

参考如下代码,通过例子,验证一遍上述的理论。

1. 带默认值的参数

在了解带星号(*)的参数之前,先看下带有默认值的参数,函数定义如下:

def defaultValueArgs(common, defaultStr = "default", defaultNum = 0):print("Common args:", common)print("Default String:", defaultStr)print("Default Number:", defaultNum)

(1)带默认值的参数(defaultStr、defaultNum)不传参时的调用:

In [26]: defaultValueArgs("Test")
Common args: Test
Default String: default
Default Number: 0

(2)带默认值的参数(defaultStr、defaultNum),调用的时候可以直接传参(如下例中的defaultStr),也可以写成“argsName = value”的形式(如下例中的defaultNum):

In [27]: defaultValueArgs("Test", "Str", defaultNum=1)
Common args: Test
Default String: Str
Default Number: 1In [28]: defaultValueArgs("Test", defaultNum=1)
Common args: Test
Default String: default
Default Number: 1

注意:在函数定义时,第一个带有默认值的参数之后的所有参数都必须有默认值,否则,运行时报错。

def defaultValueArgs(common, defaultStr = "default", defaultNum):print("Common args:", common)print("Default String:", defaultStr)print("Default Number:", defaultNum)

编译输出:

SyntaxError: non-default argument follows default argument

2.带一个星号(*)的函数参数

带一个参数的函数定义如下:

def singalStar(common, *rest):print("Common args: ", common)print("Rest args: ", rest)

(1)带星号(*)的参数不传参:

In [3]: singalStar("hello")
Common args:  hello
Rest args:  ()

带星号(*)的参数不传参时默认是一个空的元组。

(2)带星号(*)的参数传入多个值时(个数大于或等于函数定义时的参数个数):

In [4]: singalStar("hello", "world", 000)
Common args:  hello
Rest args:  ('world', 0)

不难看出,第二种方式中,星号参数把接收的多个参数合并为一个元组。

(3)当我们直接传元组类型的值给星号参数时:

In [5]: singalStar("hello", ("world", 000))
Common args:  hello
Rest args:  (('world', 0),)

此时,传递的元组值作为了星号参数的元组中的一个元素。

(4)如果我们想把元组作为星号参数的参数值,在元组值前加上" * " 即可。

In [6]: singalStar("hello", *("world", 000))
Common args:  hello
Rest args:  ('world', 0)
In [7]: singalStar("hello", *("world", 000), "123")
Common args:  hello

3.带两个星号(**)的函数参数

带两个星号(**)的函数定义如下:

(1)双星号(**)参数不传值:

In [9]: doubleStar("hello")
Common args:  hello
Double args:  {}

带双星号(**)的参数不传值时默认是一个空的字典。

(2)双星号(**)参数传入多个参数时(个数大于或等于函数定义时的参数个数):

In [10]: doubleStar("hello", "Test", 24)
TypeError: doubleStar() takes 1 positional argument but 3 were givenIn [11]: doubleStar("hello", x = "Test", y = 24)
Common args:  hello
Double args:  {'x': 'Test', 'y': 24}

可以看到,双星号参数把接收的多个参数合并为一个字典,但与单星号不同的是,此时必须采用默认值传参的 “ args = value ” 的方式,“ = ” 前的字段成了字典的键,“ = ” 后的字段成了字典的值。

(3)如果想把字典作为星号参数的参数值,那么该怎么办呢?与单星号参数类似,在字典值前加上 “ ** ”,同时其后不能添加任何值。

In [12]: doubleStar("hello", {"name": "Test", "age": 24})
TypeError: doubleStar() takes 1 positional argument but 2 were givenIn [13]: doubleStar("hello", **{"name": "Test", "age": 24}, {"name": "Test2", "age": 24})
SyntaxError: positional argument follows keyword argument unpackingIn [14]: doubleStar("hello", **{"name": "Test", "age": 24}, **{"name": "Test2", "age": 24})
TypeError: __main__.doubleStar() got multiple values for keyword argument 'name'In [16]: doubleStar("hello", **{"name": "Test", "age": 24}, **{"name1": "Test1", "age1": 24})
Common args:  hello
Double args:  {'name': 'Test', 'age': 24, 'name1': 'Test1', 'age1': 24}In [15]: doubleStar("hello", **{"name": "Test", "age": 24})
Common args:  hello
Double args:  {'name': 'Test', 'age': 24}

4. 在有些情况下,单星号函数参数和双星号函数参数是一起使用的:

In [17]: def singalAndDoubleStar(common, *single, **double):...:     print("Common args: ", common)...:     print("Single args: ", single)...:     print("Double args: ", double)In [18]: singalAndDoubleStar("hello")
Common args:  hello
Single args:  ()
Double args:  {}
In [19]: singalAndDoubleStar("hello", "world", 000)
Common args:  hello
Single args:  ('world', 0)
Double args:  {}
In [20]: singalAndDoubleStar("hello", "world", 000, {"name": "Test", "age": 24})
Common args:  hello
Single args:  ('world', 0, {'name': 'Test', 'age': 24})
Double args:  {}
In [21]: singalAndDoubleStar("hello", "world", 000, **{"name": "Test", "age": 24})
Common args:  hello
Single args:  ('world', 0)
Double args:  {'name': 'Test', 'age': 24}
In [22]: singalAndDoubleStar("hello", ("world", 000), {"name": "Test", "age": 24})
Common args:  hello
Single args:  (('world', 0), {'name': 'Test', 'age': 24})
Double args:  {}
In [23]: singalAndDoubleStar("hello", *("world", 000), {"name": "Test", "age": 24})
Common args:  hello
Single args:  ('world', 0, {'name': 'Test', 'age': 24})
Double args:  {}
In [24]: singalAndDoubleStar("hello", *("world", 000), **{"name": "Test", "age": 24})
Common args:  hello
Single args:  ('world', 0)
Double args:  {'name': 'Test', 'age': 24}

参考文章

1、Python带*参数和带**参数_猫学学的博客-CSDN博客_python带*的参数

2、python函数参数中的**_kwargspython函数参数中的**_

3、Python之可变参数,*参数,**参数,以及传入*参数,**参数解包,*args,**kwargs的理解_叫我王员外就行的博客-CSDN博客_python 参数**​​​​​​

4、https://www.jb51.net/article/206158.htm

5、Python之可变参数,*参数,**参数,以及传入*参数,**参数解包,*args,**kwargs的理解_叫我王员外就行的博客-CSDN博客_python 参数**

Python带*参数和带**参数:可变参数相关推荐

  1. python 可变参数 关键字参数_Python关键字及可变参数*args,**kw原理解析

    可变参数 顾名思义,函数的可变参数是传入的参数可以变化的,1个,2个到任意个.当然可以将这些 参数封装成一个 list 或者 tuple 传入,但不够 pythonic.使用可变参数可以很好解决该问题 ...

  2. ​Swift语言中为外部参数设置默认值可变参数常量参数变量参数输入输出参数

    ​Swift语言中为外部参数设置默认值可变参数常量参数变量参数输入输出参数 7.4.4  为外部参数设置默认值 开发者也可以对外部参数设置默认值.这时,调用的时候,也可以省略参数传递本文选自Swift ...

  3. java的可变参数介绍_Java基础 可变参数介绍(转载)

    本文章转载自:潜龙在渊的博客 一.可变参数简介 在不确定参数的个数时,可以使用可变的参数列表. 1. 语法: 参数类型...(三个点) 例如: void printArray(Object...) 注 ...

  4. python求最大值最小值_Python求可变参数的最大值最小值以及参数个数

    求可变参数的最大值最小值以及参数个数 简介: 首先要做这个题,我们要使用函数来解决,这就要求我们要掌握函数的定义以及函数的调用.函数是一段具有特定功能的.可重用的,用来实现单一,或相关联功能的代码段. ...

  5. python注解实现原理_Python3注解+可变参数实现

    一.说明 1.1 关于注解 关于注解这个东西,最早是在大学学java的时候经常会看到某些方法上边@override之类的东西,一方面不知道其作用但另一方面似乎去掉也没什么影响,所以一直都不怎么在意. ...

  6. python可变参数的特点_可变参数**kwargs传入函数时的存储方式为( )_学小易找答案...

    [单选题]抗结核药联合用药的目的是: [单选题]女性,50岁,患耐青霉素的金葡菌性心内膜炎,青霉素试敏阴性,既往有慢性肾盂肾炎,应选用: [填空题]固态下原子(或分子)呈( )排列而形成的聚集状态,称 ...

  7. Python基础教程:函数的可变参数

    在Python函数中,还可以定义可变参数. 如:给定一组数字a,b,c--,请计算a2 + b2 + c2 + --. 要定义出这个函数,我们必须确定输入的参数.由于参数个数不确定,我们首先想到可以把 ...

  8. python函数里面,一个*是可变参数的元祖,两个*是可变参数的字典

    python的函数中,有时会有类似*args,**keys这样的参数,代表的是可变参数,一个*表示元祖,两个*表示字典,就是说这个函数可以接受任何类型的参数,都不会报错,有些函数为了提高可用性,会加这 ...

  9. python 函数参数列表_Python 函数可变参数列表*args和**kwargs

    许多语言都支持可变参数列表,python也不例外.python的可变参数列表有点不太一样,有两种类型的可变参数列表,一种是元组,一种是字典. 一,元组参数列表: (1)函数定义形式:def func( ...

  10. 属于c语言高级参数的,c语言可变参数的取值

    可变参数的方法必须包含一个不可变的方法,否则会出现错误, 无法获取可变参数的长度,这和一般高级语言是有区别的. int main() { // errorTest(); enableChangePar ...

最新文章

  1. Logistic Regression逻辑回归
  2. OpenCV图像列表创建者imagelist creator的实例(附完整代码)
  3. 广州交通大学二年级算法实验题目(第一弹)
  4. 关于相机标定的问题答复网友
  5. 单播、广播、组播、多播
  6. iOS优化内存,提升性能 之五
  7. 2014北京邀请赛 F Football on Table
  8. 史上最全的面试宝典,让你轻松入职
  9. tcpdump抓SQL[转]
  10. Minecart启动器索引
  11. 第 14 章 SMS
  12. 不只是地图应用 带你走进GIS的新世界
  13. Flutter 图片透明度(光暗程度)
  14. 美国留学访学(访问学者)必备信用卡
  15. Linux计划任务要怎么弄?
  16. 以低字节为字地址是什么意思?
  17. 开源自助BI工具,傻瓜式BI分析,支持多种数据源
  18. 平面最近点距离问题(分治法)
  19. [分享] 揭开美国顶尖生物医学实验室成功的法宝--转
  20. idea提示:无法解析 文件 ‘xxx.xml‘,servelet应该有mapping

热门文章

  1. 沃通PDF签名证书 保障电子发票真实有效
  2. 高考大数据:全国31省高考难度,哪个才是地狱模式?
  3. shell wc (统计字符数量)的基本使用
  4. ipad好用的思维导图软件有哪些
  5. 一键推荐螺旋排气集污阀 螺旋除污器 螺旋脱气除污设备厂家供应
  6. 十五、2021-11-16Hadoop集群问题记录
  7. 如何修改别人的神经网络,人工神经网络通过调整
  8. 单片机中断实验2 EX0
  9. 初识pytest框架及其应用原理
  10. 涨价、盈利、IPO?共享充电宝没你想象得好过!