Python初学者应该了解的星号(*)
2020-03-23
作者:mingrammer
翻译:老齐
与本文相关的图书推荐:《Python大学实用教程》
与其他编程语言相比,Python语言的操作类型更多样化。
特别是星号(*),在Python中是一个用途广泛的操作符,而不仅仅用于两个数字相乘的运算之中。在本文中,我们将讨论星号的多种用途。
这里总结了4种星号的应用场景:
- 作为乘法和乘方的运算符
- 表示序列中元素的重复
- 用于收集参数(可以称之为“打包”)
- 用于容器类对象的解包
下面逐一进行说明。
乘法或乘方的运算符
对此你一定不陌生,像乘法一样,Python中也内置了乘方运算符。
1 | >>> 2 * 3 |
重复类列表的容器元素
Python也支持类列表的容器类对象(即序列)与整数相乘,即为按照整数实现重复其中的元素数量。
1 | # Initialize the zero-valued list with 100 length |
参数收集
很多函数中,都会有不确定个数的参数。例如,如果我们不知道要提供多少个参数,或者因为什么原因必须传任意个参数等。
在Python中有两类参数,一类是位置参数,另外一类是关键词参数,前者根据位置确定相应值,后者则是依据参数名称确定。
在研究任意个位置/关键词参数之前,先讨论确定数量的位置参数和关键词参数。
1 | # A function that shows the results of running competitions consisting of 2 to 4 runners. |
上述代码中的函数有2个位置参数:first
、second
,2个关键词参数:third
、fourth
。位置参数不能省略,必须给所有的位置参数按照其正确的位置传值。然而,对于关键词参数,在定义函数的时候你可以设置默认值,如果调用函数的时候省略了相应的实参,会以默认值作为实参,即关键词参数可以省略。
如你所见,关键词参数可以省略,所以,它们就不能在未知参数前面进行声明,如果按照下面的方式声明参数,就必然抛出异常。
1 | def save_ranking(first, second=None, third, fourth=None): |
但是,在save_ranking('alice', 'ming', 'mike', fourth='jim')
调用中,提供了3个位置实参和一个关键词参数。是的,对于关键词参数,你也可以按照位置参数的方式传值,所对应的关键词能够接受依据位置所传的数据。按照此处的调用方法,'mike'
就自动传给了third
。
以上我们已经讨论了参数的基本含义,从上述示例中,我们也能看出来,上面所定义的函数不能接收任意个数的参数,因为该函数的参数是固定数量的。因此,需要对该函数进行改造,让它能够接收任意个参数,不论是位置参数还是关键词参数。看下面的示例:
收集位置参数
1 | def save_ranking(*args): |
收集位置参数和关键词参数
1 | def save_ranking(*args, **kwargs): |
在上面的示例中,*args
意味着收集任意个数的位置参数,**kwargs
意味着收集任意个数的关键词参数。这里的*args
和**kwargs
可以称之为打包。
如你所见,在上面我们按照位置或关键词传了任意个数的参数。按照位置传的参数被收集到元组中,并用变量args
引用;以关键词传的参数则用变量kwargs
引用为字典类型。
前面提到过,关键词参数不能写在位置参数前面,所以,下面的定义方式是错误的:
1 | def save_ranking(**kwargs, *args): |
任意个数的参数很有价值,在很多开源项目中都能够看到,一般都是用*args
或者**kwargs
作为收集任意参数的名称,当然,你可以用其他名称,比如*requeired
或者**optional
等,都可以。只是对于开源项目而言,我们习惯使用*args
和**kwargs
罢了。
解包
星号还可以用于对容器的解包,这与前面的参数收集类似,比如,有一个包含数据的列表、元组或者字典,还有一个收集任意参数的函数:
1 | from functools import reduce |
因为product()
能接收任意参数,我们本来需要将列表中的元素取出来,然后传给此函数。但在这里,如果以*primes
的方式向函数提供primes
列表数据,则primes
所引用的列表会被解包,其中的每个素数都被传给函数,并被收集后用变量numbers
引用。如果传该列表primes
给函数,就不能解包,numbers
所引用的元组中只有一个primes
列表。
对于元组也如此,对于字典,需要用**
代替*
。
1 | headers = { |
还有很多种解包的实现方式,甚至于不针对函数,只是从列表、元组中取出数据,并用动态变量引用。
1 | numbers = [1, 2, 3, 4, 5, 6] |
上述操作中说明,可以分别从列表或元组中解包,得到相应值,然后用*a
和*b
引用解包所得数据,并将其打包为列表。这与前述任意个数的参数是同样的概念。
结论
以上简要介绍了Python语言中的星号(*),作为一个操作符,它有很多用途,特别是在“收集参数”中,显得很重要。但是,初学者容易在此处迷惑,所以,如果你是初学者,上面的内容要认真看一看。
原文链接:https://medium.com/understand-the-python/understanding-the-asterisk-of-python-8b9daaa4a558
搜索技术问答的公众号:老齐教室
在公众号中回复:老齐,可查看所有文章、书籍、课程。
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
关注微信公众号,读文章、听课程,提升技能