函数可变参数处理
参数收集
- 在Python中定义函数的时候可能希望函数能接收不定个数的参数,就想C中的
int printf ( const char * format, ... );
printf函数中主要利用下面三个宏实现:
#include <stdarg.h>
void va_start (va_list ap, paramN)
type va_arg (va_list ap, type)
void va_end (va_list ap)
而Python中在定义函数的时候为不定个数的参数的函数提供的参数收集的机制,如下(别看成指针了):
>>> def func_params(*params):
print params
>>> func_params(1)
(1,)
>>> func_params(1, 2, 3)
(1, 2, 3)
>>> func_params()
()
Python参数收集的机制使用星号“*”实现,这里即在指定的参数params前面加上一个“*”,“*”的意思就是用params参数收集传入是不定个数的参数,
并将收集的到参数以元组的方式存储在params中,如果没有传入参数params就是个空元组(上面第3个例子);
- 当然也可以像printf一样可变参数前面还有普通参数(const char *format),例如:
>>> def func_params1(param1, *params):
print param1
print params
>>> func_params1(1)
1
()
>>> func_params1(1, 2)
1
(2,)
>>> func_params1(1, 2, 3, 4)
1
(2, 3, 4)
>>> func_params1(1,2,3,["q"],"ww","eqwe")
1
(2, 3, ['q'], 'ww', 'eqwe')
需要注意的是不定参数后面不能再有普通参数:
>>> def func(*p, pp):
SyntaxError: invalid syntax
原因很简单因为参数p接收的全部参数那pp永远接收不到参数;
上面是函数不能处理关键字参数,如:
>>> func_params1(1, params=1)
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
func_params1(1, params=1)
TypeError: func_params1() got an unexpected keyword argument 'params'
- 关键字参数的处理可以使用“**”来实现:
>>> def func_keys(**keys):
print keys
>>> func_keys()
{}
>>> func_keys(p1=1)
{'p1': 1}
>>> func_keys(p1=1, p2=2,p3='3')
{'p2': 2, 'p3': '3', 'p1': 1}
上面再参数keys前面加上“**”,表明参数keys将接收关键字参数,并将关键字和值分别作为键-值对存储在字典中;
上面这种函数定义方式的时候,参数要么为空,要么为一个关键字参数:
>>> func_keys(1)
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
func_keys(1)
TypeError: func_keys() takes exactly 0 arguments (1 given)
- 关键字参数可以和普通参数结合使用:
>>> def func_keys1(p1, **keys):
print p1
print keys
>>> func_keys1(1)
1
{}
>>> func_keys1(1, k1=1, k2=2)
1
{'k2': 2, 'k1': 1}
同样关键字参数后面不能有普通参数了,如下:
>>> def func_keys2(**keys, p1):
SyntaxError: invalid syntax
- 关键字参数可以和可变参数结合使用:
>>> def func_keys3(*params, **keys):
print params
print keys
>>> func_keys3()
()
{}
>>> func_keys3(1,2,3)
(1, 2, 3)
{}
>>> func_keys3(1,2,k1=1,k2=2)
(1, 2)
{'k2': 2, 'k1': 1}
注意函数定义时,可变参数要在关键字参数的前面,如下错误:
>>> def func_keys4(**keys, *params):
SyntaxError: invalid syntax
- 普通参数、可变参数和关键字参数可以结合使用:
>>> def func_misc(p1, p2, p3, *params, **keys):
print p1, p2, p3
print params
print keys
>>> func_misc()
Traceback (most recent call last):
File "<pyshell#35>", line 1, in <module>
func_misc()
TypeError: func_misc() takes at least 3 arguments (0 given)
>>> func_misc(1, 2, 3)
1 2 3
()
{}
>>> func_misc(1, 2, 3, 4, 5, 6)
1 2 3
(4, 5, 6)
{}
>>> func_misc(1, 2, 3, 4, k1=1, k2=2)
1 2 3
(4,)
{'k2': 2, 'k1': 1}
>>> func_misc(1, 2, 3, k1=1, k2=2)
1 2 3
()
{'k2': 2, 'k1': 1}
同样混合使用的时候需要注意参数的位置,记住普通参数的位置要在最前面,而可变参数的位置要在关键字参数的前面;
参数收集的反转过程
在参数收集中可以使用“*”和“**”分别将参数收集为元组和字典,同样可以实现其反转过程,可以使用“*”和“**”执行相反的操作;如:
- “*”反转操作:
>>> def func(p1, p2):
print p1
print p2
>>> t=(1,2)
>>> func(*t)
1
2
元组(1,2)被反转为1,2
- “**”反转操作:
k={'p1':1, 'p2':2, 'p3':3}
>>> def func_k(p1, p2, p3):
print p1, p2, p3
>>> func_k(**k)
1 2 3
>>> def func_k1(p1):
print p1
>>> func_k1(**k)
Traceback (most recent call last):
File "<pyshell#46>", line 1, in <module>
func_k1(**k)
TypeError: func_k1() got an unexpected keyword argument 'p2'
>>> def func_k2(p1,p2,p3,p4=1):
print p1,p2,p3
print p4
>>> func_k2(**k)
1 2 3
1
>>>
字典k的反转操作后变为p1=1,p2=2,p3=3,直接放到参数表中;
以上代码均在Python 2.5.4 测试。