Python函数可变参数args及kwargs释义

Python函数可变参数args及kwargs释义

(1)前言:
看Python源码时,特别是看一些库的源码时,经常会看到func(*args, **kwargs)这样的函数定义,这个*和**让人经常感到一头雾水。其实只要把函数参数定义搞清楚了,就不难理解了。
(2)概述:
python函数可变参数 (Variable Argument) 的方法:使用*args和**kwargs语法。其中,*args是可变的positional arguments列表(位置参数列表),**kwargs是可变的keyword arguments列表(关键字参数列表)。并且,*args必须位于**kwargs之前,因为positional arguments必须位于keyword arguments之前。
1)简要说明:
下面通过一个简单的例子来解释Python函数可变参数args及kwargs的意思:
*args表示任何多个无名参数,它是一个tuple
**kwargs表示关键字参数,它是一个dict
同时使用*args和**kwargs时,*args参数列必须要在**kwargs前,要是像foo(1,a=1,b=2,c=3,2,3)这样调用的话,则会提示语法错误“SyntaxError: non-keyword arg after keyword arg”。
测试代码如下:
[wo@hai yz_test]$ more test_args.py 
def foo(*args,**kwargs):
    print 'args=',args,"len:",len(args)
    print 'kwargs=',kwargs,"len:",len(kwargs)
    print '**********************'
             
if __name__=='__main__':
    foo(1,2,3)
    foo(a=1,b=2,c=3)
    foo(1,2,3,a=1,b=2,c=3)
    foo(1,'b','c',a=1,b='b',c='c')
执行结果如下:
[wo@hai yz_test]$ python test_args.py 
args= (1, 2, 3)
kwargs= {}
**********************
args= ()
kwargs= {'a': 1, 'c': 3, 'b': 2}
**********************
args= (1, 2, 3)
kwargs= {'a': 1, 'c': 3, 'b': 2}
**********************
args= (1, 'b', 'c')
kwargs= {'a': 1, 'c': 'c', 'b': 'b'}
**********************
(2)python函数传参几种类型:
1)调用函数的时候,传递的参数都是根据位置来跟函数定义里的参数表匹配的,比如funcB(100, 99)和funcB(99, 100)的执行结果是不一样的。
2)在Python里,还支持一种用关键字参数(keyword argument)调用函数的办法,也就是在调用函数的时候,明确指定参数值付给那个形参。比如还是上面的funcB(a, b),我们通过这两种方式调用funcB(a=100, b=99)和funcB(b=99, a=100)结果跟funcB(100, 99)都是一样的,因为我们在使用关键字参数调用的时候,指定了把100赋值给a,99赋值给b。也就是说,关键字参数可以让我们在调用函数的时候打乱参数传递的顺序!
3)另外,在函数调用中,可以混合使用基于位置匹配的参数和关键字参数,前题是先给出固定位置的参数,比如
def funcE(a, b, c):
  print a
  print b
  print c
调用funcE(100, 99, 98)和调用funcE(100, c=98, b=99)的结果是一样的。
4)如果一个函数定义中的最后一个形参有 ** (双星号)前缀,所有正常形参之外的其他的关键字参数都将被放置在一个字典中传递给函数,比如:
def funcF(a, **b):
  print a
  for x in b:
    print x + ": " + str(b[x])
调用funcF(100, c='你好', b=200),执行结果
100
c: 你好
b: 200
可以看到,b是一个dict对象实例,它接受了关键字参数b和c。
常规参数,*参数及**参数可以同时使用,具体怎么用?看看Python Reference Manual吧,关于Function definitions的那些章节。
(4)其他例子:
1)下面一个例子使用*args,同时包含一个必须的参数:
def test_args(first, *args):
   print 'Required argument: ', first
   for v in args:
      print 'Optional argument: ', v
test_args(1, 2, 3, 4)

[wo@hai yz_test]$ python 11_test.py 
Required argument:  1
Optional argument:  2
Optional argument:  3
Optional argument:  4
2)下面一个例子使用*kwargs, 同时包含一个必须的参数和*args列表:
def test_kwargs(first, *args, **kwargs):
   print 'Required argument: ', first
   for v in args:
      print 'Optional argument (*args): ', v
      for k, v in kwargs.items():
          print 'Optional argument %s (*kwargs): %s' % (k, v)
test_kwargs(1, 2, 3, 4, k1=5, k2=6)
[wo@hai yz_test]$ python 11_test.py 
Required argument:  1
Optional argument (*args):  2
Optional argument k2 (*kwargs): 6
Optional argument k1 (*kwargs): 5
Optional argument (*args):  3
Optional argument k2 (*kwargs): 6
Optional argument k1 (*kwargs): 5
Optional argument (*args):  4
Optional argument k2 (*kwargs): 6
Optional argument k1 (*kwargs): 5
(5)其他理解:
*args和**kwargs语法不仅可以在函数定义中使用,同样可以在函数调用的时候使用。不同的是,如果说在函数定义的位置使用*args和**kwargs是一个将参数pack的过程,那么在函数调用的时候就是一个将参数unpack的过程了。下面使用两例子加深理解:
1)使用*args的例子
# Use *args
def test_args(args):
    print args
    print type(args)
    for e in args:
        print e
args = [1, 2, 3, 4, 5]  
test_args(*args)
 [wo@hai yz_test]$ python 11_test.py 
Traceback (most recent call last):
  File "11_test.py", line 7, in <module>
    test_args(*args)
TypeError: test_args() takes exactly 1 argument (5 given)
改成如下格式:
def test_args(*args):
    print args
    print type(args)
    for e in args:
        print e
args = [1, 2, 3, 4, 5]  
test_args(*args)
[wo@hai yz_test]$ python 11_test.py 
(1, 2, 3, 4, 5)
<type 'tuple'>
1
2
3
4
5
2) 使用**kwargs的例子
# Use **kwargs
def test_args(*args):
    print args
    print type(args)
    for e in args:
        print e, args[e]
[wo@hai yz_test]$ python 11_test.py 
Traceback (most recent call last):
  File "11_test.py", line 16, in <module>
    test_args(**kwargs)
TypeError: test_args() got an unexpected keyword argument 'second'
改成如下形式:
[wo@hai yz_test]$  more 11_test.py 
def test_args(**args):
    print args
    print type(args)
    for e in args:
        print e, args[e]
# Use **kwargs
kwargs = {
    'first': 1,
    'second': 2,
    'third': 3,
    'fourth': 4,
    'fifth': 5
    }
test_args(**kwargs)
[wo@hai yz_test]$ python 11_test.py 
{'third': 3, 'second': 2, 'fourth': 4, 'fifth': 5, 'first': 1}
<type 'dict'>
third 3
second 2
fourth 4
fifth 5
first 1
参考网址:若还是不能理解的话,建议阅读这篇文章:

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值