*运算符适用于元组或者列表型变量,**运算符适用于字典型变量。本文主要解释在进行函数传参的时候这两者的应用方式及原理。
*运算符:
(1)当作为函数的形参的时候
结果:
哎奇怪了,怎么会出现这样的结果呢?
首先明确,函数参数里的*并不代表着传入的参数一定是列表,而是代表着这里可以接受任意多个无名参数。可以参考这篇文章:
好了,现在我们知道这个*args代表的真正含义了,它并不代表着传入的参数一定是列表。那为什么传入的list没有被当做列表来处理呢?
我们来想想,对于fun(*args)来说,所接受的参数应该是fun(var_1,var_2,...,var_n)的形式,那么,args的元素应该是var_1,var_2,...,var_n,相当于存储的是一个一个的变量。而这里的list,本质上来说就是一个列表类型的变量而已,作为一个整体被传入函数中,args里面实际上只有一个元素,就是一个列表类型的变量list!
实际上,fun函数里执行的语句是这样的:
打印出来的就是以列表的形式显示的list变量,会把括号带上~
所以说,作为函数形参的时候,其实*跟列表的解引用一点关系也没有~
我们来看这种用法的一个实例:
结果:
实际上就是接受了传入的所有参数,args本质上是一个列表,里面的元素就是传入的参数,比如这里就是args=["a","star",135]
那么,我们有没有向函数里面传入列表的各个元素的方法呢?
(2)当作为函数的实参的时候
可以比较一下,跟上面代码基本相同,只有最后一行有所差别。
结果:
现在我们发现, 打印出了列表内部的元素,也就是说,作为函数实参的时候,*list表示对列表list的解引用,*list事实上是向函数内部传入了两个字符串参数‘Hello'和'World'!
**运算符:
有了*运算符的基础,其实**运算符是完全类似的。
(1)当作为函数的形参的时候
首先我们举一个跟上面类似的例子,
这一次报错了,没有输出结果。原因很简单,**运算符在这里是代表允许接受任意多个键值对,而传入的是一个字典型的变量,并不是一个键值对,类型不匹配当然就报错了。
正确实例:
args本质上是一个字典,里面的元素就是传入的键值对,比如这里就是args=["X":"x","Y":"y","Z":"z"]
注意,向函数里面传键值对的格式跟定义字典型变量的格式是不一样的,向函数里面传键值对的格式是{key=value},而定义字典型变量的格式是{"key":value},但是key都是字符串,value类型可以多样。
(2)当作为函数的实参的时候
作为函数实参的时候,**dir表示对字典dir的解引用,**dir事实上是向函数内部传入了三个键值对参数:key1="X",value1="x",key2="Y",value2="y",key3="Z",value3="z",可以看到输出的结果完全相同。
总结:
*运算符:在作为函数形参时,代表接受任意多个参数,本质上是接收参数构成的列表型变量;
在作为函数传入实参时,代表对元组/列表进行解引用,将元组/列表的多个元素分别传入而不是作为一个整体元组/列表型变量传入。
**运算符:在作为函数形参时,代表接受任意多个键值对,本质上是接收键值对构成的字典型变量;
在作为函数传入实参时,代表对字典进行解引用,将字典的多个键值对分别传入而不是作为一个整体字典型变量传入。
文章评论