在编写函数时, *args
和 **kwargs
可以使我们向函数传递任意数量的参数(Arbitrary Argument Lists)
*args
将函数的普通参数打包成元组的形式:
1 2 3 4 5 6 7 8 9 10 11 >>> def foo (*args) :... print(type(args))... for a in args:... print(a)... >>> >>> foo(1 , 'a' , [1 , 2 , 3 ])<class 'tuple '> 1 a [1, 2, 3]
**kwargs
将带有关键字的参数打包成字典的形式:
1 2 3 4 5 6 7 8 9 10 11 >>> def bar (**kwargs) :... print(type(kwargs))... for a in kwargs:... print(a, kwargs[a])... >>> >>> bar(a=1 , b='a' , c=[1 , 2 , 3 ])<class 'dict '> a 1b a c [1, 2, 3]
普通参数、*args
、 **kwargs
都可以混合使用
1 2 def foo (kind, *args, **kwargs) : pass
另外, *
与 **
还可以起到解包的作用,将元组、列表、字典等解包,作为参数传递给函数
*
可以将列表解包成普通函数参数的形式:
1 2 3 4 5 6 def foo (bar, lee) : pass l = [1 , 2 ] foo(*l)
例如在 zip
函数中:
1 2 3 4 5 6 7 8 >>> a = [1 , 2 , 3 ]>>> b = [4 , 5 , 6 ]>>> zipped = list(zip(a, b))>>> print(zipped)[(1 , 4 ), (2 , 5 ), (3 , 6 )] >>> unzipped = list(zip(*zipped))>>> print(unzipped)[(1 , 2 , 3 ), (4 , 5 , 6 )]
**
可以将字典解包成带关键字的函数参数形式,比如在tensorflow中:
1 2 3 4 5 6 initializer_helper = { 'kernel_initializer' : tf.random_normal_initializer(0. , 0.1 ), 'bias_initializer' : tf.constant_initializer(.1 ) } tf.layers.dense(foo, bar, **initializer_helper)
相当于是:
1 2 3 4 5 tf.layers.dense( foo, bar, kernel_initializer=tf.random_normal_initializer(0. , 0.1 ), bias_initializer=tf.constant_initializer(.1 ) )
可以省去每次写一堆重复关键字参数的代码
如果你爱Python这门语言,就少用一些你觉得爽但是别人会mmp的语法了。告诉我,当你看到别人写的函数有**kwargs这样的参数,你不想问候他祖宗十八代吗?
😂 知乎:如何看待知乎、饿了么后端的招聘纷纷由 Python 渐渐转向 Java?
参考
https://stackoverflow.com/questions/36901/what-does-double-star-asterisk-and-star-asterisk-do-for-parameters
https://docs.python.org/dev/tutorial/controlflow.html#more-on-defining-functions