在python编程中经常见到星号*和**,这里对其含义进行介绍。


一、普通含义

** 在python里面表示幂运算

二、传递实参和定义形参

所谓实参就是调用函数时传入的参数,形参则是定义函数是定义的参数。
这个操作类似于提取、解压。

1、调用函数时使用*

test(*args),星号的作用其实就是把序列 args 中的每个元素,当作位置参数传进去。比如test(*args)这个代码,如果 args 等于 (1,2,3) ,那么这个代码就等价于 test(1, 2, 3) 。

def foo(a,b):
    print(a)
    print(b)

args = [1,2]   #这里只能有两个元素
foo(*args)

得到的结果为

1
 2

2、调用函数时使用**

test(**kwargs),双星号的作用则是把字典 kwargs 变成关键字参数传递。比如test(**kwargs)这个代码,如果 kwargs 等于 {“a”:1,“b”:2,“c”:3} ,那这个代码就等价于 test(a=1,b=2,c=3) 。

def foo(a,b):
    print(a)
    print(b)

kwargs = {'a':1,'b':2}   #这里只能是'a'和'b'
foo(**kwargs)

得到的结果为

1
 2

三、定义函数参数时使用

参数前面加上星号 ,意味着参数的个数不止一个,另外带一个星号参数的函数传入的参数存储为一个元组(tuple),带两个星号则是表示字典(dict)。
参数带星号表示支持可变不定数量的参数,这种方法叫参数收集。
星号又可以带1个或2个,带1个表示按位置来收集参数,带2个星号表示按关键字来收集参数。

1、带一个星号的参数收集模式

这种模式是在函数定义时在某个形参前面加一个星号,调用时按位置匹配不带星号的形参和实参,多余的实参都将作为一个元组的元素保存到星号对应的形参中。

def test(*args):
	...

定义函数参数时 * 的含义,如这里 *args 表示把传进来的位置参数都装在元组 args 里面。比如说上面这个函数,调用 test(1, 2, 3) 的话, args 的值就是 (1, 2, 3) 。

示例如下:

def foo(a, b, c, *args):
    print("a = %s" % (a,))
    print("b = %s" % (b,))
    print("c = %s" % (c,))
    print(args)

foo("testa", "testb", "testc", "excess", "another_excess")

得到的结果为

a = testa
 b = testb
 c = testc
 (‘excess’, ‘another_excess’)

在这里,由于我们在测试位置参数,多余的参数必须在末尾,并且*args将它们打包成一个元组。

2、带两个星号的参数收集模式:

带一个星号的参数收集模式的收集参数不能收集关键字参数传递的实参,要收集关键字参数传递的实参,需要在收集参数前使用两个星号,此时收集参数对应的是一个字典而不是元组。

def test(**kwargs):
	...

类似的, ** 就是针对关键字参数和字典的了。 调用 test(a=1,b=2,c=3) 的话, kwargs 的值就是 {“a”:1,“b”:2,“c”:3} 了。

普通的参数定义和传递方式和 * 们都可以和平共处,不过显然 * 必须放在所有位置参数的最后,而 ** 则必须放在所有关键字参数的最后,否则就要产生歧义了。

示例如下:

def foo(a, b, c, **kwargs):
    print("a = %s" % (a,))
    print("b = %s" % (b,))
    print("c = %s" % (c,))
    print(args)

foo(a="testa", d="excess", c="testc", b="testb", k="another_excess")
foo("testa", "testc", "testb", d="excess", k="another_excess")

得到的结果为

a = testa
 b = testb
 c = testc
 {‘d’: ‘excess’, ‘k’: ‘another_excess’}a = testa
 b = testc
 c = testb
 {‘d’: ‘excess’, ‘k’: ‘another_excess’}

也就是说,在foo函数的签名中只有参数a, b, c。由于d和k不存在,它们被放入args字典。

四、综合示例

例1

def foo(a,b,c,*args):
    print("a=%s" % (a,))
    print("b=%s" % (b,))
    print("c=%s" % (c,))
    print("args=%s" % (args,))

argtuple = ("testa","testb","testc","excess1","excess2")
foo(*argtuple)

得到的结果为

a=testa
b=testb
c=testc
args=(‘excess’,‘excess2’)

例2

def foo(a,b,c,**args):
    print("a=%s" % (a,))
    print("b=%s" % (b,))
    print("c=%s" % (c,))
    print("args=%s" % (args,))

argdict = dict(a="testa", b="testb", c="testc", excessarg="string")
foo(**argdict)

得到的结果为

a=testa
 b=testb
 c=testc
 args={‘excessarg’: ‘string’}

例3

def foo(a,b,*args,**kwargs):
    print(a)
    print(b)
    print(args)
    print(kwargs)

foo(1,2,3,4,e=5,f=6)

得到结果为

1
 2
 (3, 4)
 {‘e’: 5, ‘f’: 6}