在学习Python “装饰器“的过程中,会看到这样一种写法

def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

表示,,一脸懵逼。在C语言中,* 表示指针,**表示指针的指针,在Python中,这又是哪种说法。

先说函数定义:

def funA():
   print("funA")

显然,funA 没定义任何参数

下面,带参的函数funB

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

调用的时候,我们需要使用函数名,funB(10,9),执行结果是 10,9

很显然,参数的顺序和个数要和函数保持一致,如果执行funB(19),Python 会报错,

TypeError: funB() missing 1 required positional argument: 'b'

我们可以在函数定义中使用默认值,比如:

def funC(a,b=0):
   print(a,b)

在函数funC中,b 有个默认值,是一个可选参数,如果我们调用funC(100),b 会自动赋值0

目前为止,我们知道在定义一个函数的时候,必须预先定义这个函数需要多少个参数,如果不知道参数个数的情况,在Python中,带* 参数就是用来接收可变数量参数。

def funD(a,b,*c):
   print("a:",a)
   print("b:",b)
   print("length of c is %d:" %len(c))
   print("c:",c)
调用函数,funD(1,2,3,4,5,6),输出 

a: 1
b: 2
length of c is 4:
c: (3, 4, 5, 6)

我们看到,前面两个参数被a、b接受了,剩下的4个参数,全部被c接受了,c在这里是一个tuple。我们在调用funcD的时候,至少要传递2个参数,2个以上的参数,都放到c里了,如果只有两个参数,那么c就是一个empty tuple。

下面讨论两颗*

在Python里,还支持一种用关键字参数(keyword argument)调用函数的办法,明确指定参数值赋给哪个形参。比如还是上面的funcB(a, b),我们通过这两种方式调用

funB(a=100,b=99)

funB(b=99,a=100)

结果跟funB(100,99) 都是一样的,因为我们在使用关键字参数调用的时候,指定了把100赋值给a,99赋值给b。也就是说,关键字参数可以让我们在调用函数的时候打乱参数传递的顺序!

在函数调用中,可以混合使用基于位置匹配的参数和关键字参数,前题是先给出固定位置的参数,

def funE(a,b,c):
   print(a)
   print(b)
   print(c)

调用funE(1,2,3) 和funE(1,c=3,b=2) 的结果是一样的

下面,两颗星正式登场:

如果一个函数定义中的最后一个形参有 ** (双星号)前缀,所有正常形参之外的其他的关键字参数都将被放置在一个字典中传递给函数,比如:

def funF(a,**b):
   print(a)
   for i in b:
      print(i + ":" + str(b[i]))
funF(1,c="您好",b=200) 执行结果:

1
b:200
c:您好

 可以看到,b 是一个dict 对象实例,接收了关键字参数b 和c