• Python中的魔法参数:*args和**kwargs的用法
  • 发布于 2个月前
  • 232 热度
    0 评论
  • 无花果
  • 1 粉丝 5 篇博客
  •   
在写函数的时候,经常要写形参,我们经常看到*args和**kwargs, 这到底是什么,怎么用呢?在Java中,有个定义是重载: 函数名可以相同,参数个数不同,或者类型不同,是不同的方法(函数),有的时候参数不同,要写好几个同名的函数。

python似乎做了一些改进,就是用魔法参数:*args和**kwargs。 管你多少个参数,管你什么类型,我都可以扔到这两个里面。这就减少了重复写同名函数。
*args和**kwargs,以及单独的∗,∗∗到底是啥作用呢?
*args有两部分构成为——∗和args。这里的重点是∗。
所以为了讲清楚*args,我们要追根溯源——理解∗的作用。
*的作用—— 打包参数(pack)和拆分参数(unpack)!
打包参数(pack)
例1:
def foo(*number):
    print(number)
    print(type(number))
foo(1, 2, 3, 4, 5)
结果:
(1, 2, 3, 4, 5)
<class 'tuple'>
给函数5个参数,成功运行了,而且输出是参数构成的元组。我们知道,如果number前不加∗∗号,那么很明显foo()只能接受1个参数,参数给多了少了都要报错。而加上∗∗,就能成功运行。
∗把函数foo()接受到的多个参数1,2,3,4,5,打包成了元组(1,2,3,4,5),赋值给了形参number。
例2:
def foo2(a,*number):
    print("a:{}".format(a))
    print("number:{}".format(number))
    print(type(number))
foo2(1, 2, 3, 4, 5)
结果:
a:1number:(2, 3, 4, 5)
<class 'tuple'>
从例中可以看出,number接受到的实参变成了(2,3,4,5),第一个参数1被形参a接受走了。
∗的作用:函数接受实参时,按顺序分配给函数形参,如果遇到带∗∗的形参,那么就把还未分配出去的实参以元组形式打包(pack),分配给那个带∗的形参。

拆分参数(unpack)
def foo3(a,b,c):
    print(a,b,c)
foo3(*[1,2,3])
把打包了的实参(元组或列表),拆分(unpack)成单个的,依次赋值给函数的形参。
在本例中,打包了的实参[1,2,3]被拆分,1赋值给了形参a,2赋值给了形参b,3复制给了形参c。
注意: 形参个数必须跟列表长度一样,不然就有实参没有接受的形参。

**kwargs
打包(pack):args是把多个位置参数打包成元组,kwargs是把多个关键字参数打包成字典。
拆分(unpack):args是把打包了的参数拆成单个的,依次赋值给函数的形参,**kwargs是把字典的键值拆成单个的,依次赋值给函数的形参。

Pack
def bar(**number):
    print(number)
bar(a=1, b=2, c=3)
结果:
{'b': 2, 'c': 3, 'a': 1}

(unpack)
def bar(a, b, c):
    print(a,b,c)
bar(**{'a': 1, 'b': 2, 'c': 3})

结果:
1 2 3
就是用∗∗方式拆解字典给形参赋值时,需要字典的键名和函数形参一直,否则会报错。

混用
当要同时使用*args和**kwargs时,*args必须写在**kwargs之前。
我们来看例子:
def foo(*args, **kwargs):
    print ('args = ', args)    print ('kwargs = ', kwargs)    print ('---------------------------------------')if __name__ == '__main__':
    foo(1 ,2 ,3 ,4)
foo(a=1 ,b=2 ,c=3)
foo(1 ,2 ,3 ,4, a=1 ,b=2 ,c=3)
foo('a', 1, None, a=1, b='2', c=3)
我们来看结果:
args =  (1, 2, 3, 4)
kwargs =  {}
---------------------------------------
args =  ()
kwargs =  {'b': 2, 'c': 3, 'a': 1}
---------------------------------------
args =  (1, 2, 3, 4)
kwargs =  {'b': 2, 'c': 3, 'a': 1}
---------------------------------------
args =  ('a', 1, None)
kwargs =  {'b': '2', 'c': 3, 'a': 1}
---------------------------------------
可以看到,这两个是python中的可变参数。*args表示任何多个无名参数,它是一个tuple;**kwargs表示关键字参数,它是一个 dict。并且同时使用*args和**kwargs时,必须args参数列要在**kwargs前,像foo(a=1, b=’2′, c=3, a’, 1, None, )这样调用的话,会提示语法错误“SyntaxError: non-keyword arg after keyword arg”。

所以python里面就没有重载,只需要写一个方法,加上魔法参数,就万事大吉。
用户评论