在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
14
In [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
9
In [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
2
def foo(kind, *args, **kwargs):
pass

解包参数列表

在Python中,调用函数时,利用*语句可以将参数列表解包,如下所示,foo有两个参数,我们可以传入一个参数列表l,然后利用*运算符,解包参数列表:

1
2
3
4
5
6
7
8
9
In [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', 'dave@example.com', '773-555-1212', '847-555-1212')
>>> name, email, *phone_numbers = record
>>> name
'Dave'
>>> email
'dave@example.com'
>>> 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
2
def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
pass

这个函数只接受3个位置参数,*之后的所有内容只能作为关键字参数传递(只能由关键字提供的参数,并且永远不会被位置参数自动填充)。

Reference