在Python中,我们经常可以见到**和*运算符,比如*args 和 **kwargs,还有n**3、*nums等等。这里总结一下,在Python中 **和*的用法。
数学运算符
它们作为数学运算符是非常简单的:
*用于乘法
**用于乘方
1
2
3
4>>>2 * 6
12
>>>2 ** 6
64
函数参数
*args 和 **kwargs 主要用于函数定义,是一种允许任意数量(即预先并不知道函数使用者会传递多少个参数给)的函数参数的习惯用法,可以参见Python的官方文档。
首先并不是必须写成*args 和**kwargs。 只有变量前面的 *(星号)才是必须的,也可以写成*var和**vars。 而写成*args 和**kwargs只是一个通俗的命名约定。
*args
*args是可变参数。*args 可以表示任意多个参数,它本质是一个 tuple。
1
2
3
4
5
6
7
8
9
10
11
12
13
14In [1]: def foo(*args):
...: for a in args:
...: print a
...:
...:
In [2]: foo(1)
1
In [4]: foo(1,2,3)
1
2
3
** **kwargs**
**kwargs是关键字参数,它本质上是一个 dict。
1
2
3
4
5
6
7
8
9In [5]: def bar(**kwargs):
...: for a in kwargs:
...: print a, kwargs[a]
...:
...:
In [6]: bar(name='one', age=27)
age 27
name one
*args 和 **kwargs都可以与普通参数混合,以允许向函数传递一组固定参数和一些可变的参数:
在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
因此,如果同时使用 *args 和 **kwargs 时,*args 参数必须要在 **kwargs 之前。
1
2def foo(kind, *args, **kwargs):
pass
解包参数列表
在Python中,调用函数时,利用*语句可以将参数列表解包,如下所示,foo有两个参数,我们可以传入一个参数列表l,然后利用*运算符,解包参数列表:
1
2
3
4
5
6
7
8
9In [9]: def foo(bar, lee):
...: print bar, lee
...:
...:
In [10]: l = [1,2]
In [11]: foo(*l)
1 2
序列解包
在Python3.0之后,Python提供了一种非常方便的办法解压可迭代对象赋值给多个变量 (Extended Iterable Unpacking)。
另外一种情况,假设你现在有一些用户的记录列表,每条记录包含一个名字、邮件,接着就是不确定数量的电话号码。 你可以像下面这样分解这些记录:
1
2
3
4
5
6
7
8>>>record = ('Dave', '[email protected]', '773-555-1212', '847-555-1212')
>>>name, email, *phone_numbers = record
>>>name
'Dave'
>>>phone_numbers
['773-555-1212', '847-555-1212']
值得注意的是上面解压出的 phone_numbers 变量永远都是列表类型,不管解压的电话号码数量是多少(包括 0 个)。 所以,任何使用到 phone_numbers 变量的代码就不需要做多余的类型检查去确认它是否是列表类型了。
星号表达式也能用在列表的开始部分。比如,你有一个公司前 8 个月销售数据的序列, 但是你想看下最近一个月数据和前面 7 个月的平均值的对比。你可以这样做:
1
2
3*trailing_qtrs, current_qtr = sales_record
trailing_avg = sum(trailing_qtrs) / len(trailing_qtrs)
return avg_comparison(trailing_avg, current_qtr)
下面是在 Python 解释器中执行的结果:
1
2
3
4
5>>>*trailing, current = [10, 8, 7, 1, 9, 5, 10, 3]
>>>trailing
[10, 8, 7, 1, 9, 5, 10]
>>>current
3
Keyword-Only Arguments
在Python3中,也加入了一个新的语法(参见 PEP 3102)
1
2def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
pass
这个函数只接受3个位置参数,*之后的所有内容只能作为关键字参数传递(只能由关键字提供的参数,并且永远不会被位置参数自动填充)。
Reference