Python-*和**运算符

在Python里面,***具备多重含义,目前接触到的有以下几类用法:

  • 代数运算
  • 函数传参
  • 序列解包

代数运算

1
2
3
4
5
6
>>> a = 3*5
>>> a
15
>>> b = 3**5
>>> b
243

函数传参

*args**kwargs常见于函数定义,其实写成别的名字也行,大家都习惯而已。写成*a*ka也可以。Python中,函数传递参数的方式有两种:

  • 位置参数:positional argument
  • 关键词参数:keyword argument

举个例子:

1
2
3
4
5
>>> def f(a=1,b=2):
... return a*2+b
...
>>> print(f(b=1,a=2))
5

这个上面,参数的位置反了,但是Python还是能识别出来,就可以理解为关键词参数。在Python中,*args**kwargs都是可变参数,在同时使用二者时,我们认为规定*args必须要在**kwargs前面,二者的区别如下:

  • *args:表示多个无名参数,本质上是一个tuple
  • **kwargs:表示关键字参数,本质上是一个dict

我们举个例子:

1
2
3
4
5
6
7
>>> def func(*args, **kwargs):
... print("args = ", args)
... print("kwargs = ", kwargs)
...
>>> func(1, 2, A='a', B='b', C='c')
args = (1, 2)
kwargs = {'A': 'a', 'B': 'b', 'C': 'c'}

也可以单独使用,首先使用*args,样例如下:

1
2
3
4
5
6
7
8
9
>>> def func(name, *args):
... print("hi: ", name)
... for item in args:
... print("hello, ", item)
...
>>> func("Alice", "Bob", "Carl")
hi: Alice
hello, Bob
hello, Carl

同理,**kwargs当然也是可以单独使用的,样例如下:

1
2
3
4
5
6
7
>>> def func(**kwargs):
... for k,v in kwargs.items():
... print("{0} likes {1}".format(k,v))
...
>>> func(Alice='cat', Bob='dog')
Alice likes cat
Bob likes dog

序列解包

序列解包目前只接触过 *运算符,没有接触过 **

1
2
3
4
5
6
7
>>> a, b, *c = 1, 2, 3, 4
>>> a
1
>>> b
2
>>> c
[3, 4]
1
2
3
>>> a = [1, 2]
>>> print(*a)
1 2

结合函数传参,***运算法可以这么理解:

1
2
**{'a':1, 'b':2} => 'a'=1,'b'=2
*[1,2] => 1,2

疑问&尝试

其实讲道理,函数传参和解包当中的*应该是同一个用法,所以我在想**为啥不能用到dict上面呢,于是我试了一下下面的代码,不过出错了:

1
2
3
4
5
6
>>> d = {'a':1,'b':2,'c':3}
>>> print(**d)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'a' is an invalid keyword argument for this function
>>>

看来,**只能在函数传参当中使用了。

Thanks for rewarding