问题
阅读源码时,发现*运算符和**运算符修饰在函数定义参数前,如下代码所示:
def foo(x, y, *args):
pass
def bar(x, y, **kwargs):
pass
星号运算符在基础数学运算中,*表示乘法运算符,**表示指数运算符。
看来*运算符、**运算符还有另有他用。
解答
一
*args
表示传递给函数一系列的参数,专业术语称之为“可变参数列表”(Arbitrary Argument Lists),与Java的“…”类似:
>>> def foo(*args):
... for a in args:
... print(a)
...
>>> foo(1)
1
>>> foo(1,2,3)
1
2
3
>>>
>>> def concat(*args, sep="/"):
... return sep.join(args)
...
>>> concat("earth", "mars", "venus")
'earth/mars/venus'
>>> concat("earth", "mars", "venus", sep=".")
'earth.mars.venus'
*args
将位置参数们(positional arguments)打包成元组处理。
二
另外,函数定义参数前有**双星运算符修饰,它表示将关键词参数(keyword arguments)打包成字典处理:
>>> def bar(**kwargs):
... for a in kwargs:
... print(a, kwargs[a])
...
>>> bar(name='one', age=27)
name one
age 27
三
*运算符和**运算符可混合使用,但*修饰的参数必须在**修饰的参数的前面位置:
>>> def cheeseshop(kind, *arguments, **keywords):
... print("-- Do you have any", kind, "?")
... print("-- I'm sorry, we're all out of", kind)
... for arg in arguments:
... print(arg)
... print("-" * 40)
... for kw in keywords:
... print(kw, ":", keywords[kw])
...
>>> cheeseshop("Limburger", "It's very runny, sir.",
... "It's really very, VERY runny, sir.",
... shopkeeper="Michael Palin",
... client="John Cleese",
... sketch="Cheese Shop Sketch")
...
-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
shopkeeper : Michael Palin
client : John Cleese
sketch : Cheese Shop Sketch
四
最后,*运算符另有它用。上文介绍了*args
将位置参数们打包成元组处理,*运算符也可以起反作用,也就是将列表或元组解压成对应位置参数,专业术语称之为“解包参数列表”(Unpacking Argument Lists):
>>> list(range(3, 6)) # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args)) # call with arguments unpacked from a list
[3, 4, 5]
类似的,**可以将字典解压成关键词参数:
>>> def parrot(voltage, state='a stiff', action='voom'):
... print("-- This parrot wouldn't", action, end=' ')
... print("if you put", voltage, "volts through it.", end=' ')
... print("E's", state, "!")
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !