# python中的*args和**kargs
# 1.函数的参数基础
Python
中函数参数从不同角度可分为几种类型,包括
- 1)必备参数:函数调用时必须赋值的参数。
- 2)可选参数:函数调用时可以省略的参数。
- 3)位置参数:函数调用时通过参数位置顺序来赋值的参数。
- 4)关键字参数:函数调用时通过关键字来赋值的参数(可不按顺序)。
# 1.1 示例:必备参数
必备参数:调用函数时必须要赋值的那些参数,通常是不带默认值的参数。如下:
def add(x, y):
print(f"x={x}")
print(f"y={y}")
print(x + y)
return x + y
调用时,若只通过传值按顺序传入参数,则对应的参数变成了位置参数:
# x,y此时都是位置参数
>>>add(2,3)
x=2
y=3
5
调用时,若通过关键字键值对传入参数,则对应的参数将变成关键字参数:
# x,y此时都是关键字参数
>>>add(x=3, y=4)
x=3
y=4
7
# 或者
>>>add(y=2,x=3)
x=3
y=2
5
# 1.2 示例:可选参数
可选参数函数调用时可以省略的参数。例如:
def add(x=0, y=1):
print(f"x={x}")
print(f"y={y}")
print(x + y)
return x + y
调用时可通过位置或关键字传入。
# 按关键字 传入
>>>add(x=2,y=3)
x=2
y=33
5
>>>add(y=3,x=2)
x=2
y=33
5
# 按位置传入
>>>add(2,3)
x=2
y=3
5
# 省略 y, 使用默认y=1
>>>add(x=2)
x=2
y=1
3
# 省略 x, 使用默认x=0
>>>add(y=12)
x=0
y=12
12
# x按位置传入,y按关键字传入
>>>add(10,y=12)
x=10
y=12
12
# error, 位置参数必须在关键字参数前使用
# 函数定义时,必备参数必须在可选参数之前
>>>add(x=10,12)
SyntaxError: positional argument follows keyword argument
# 2.不定长参数
不定长参数,就是函数函数的个数是不确定的,如以上add
函数,有可能是任意个数字的和,这个时候就用用到了不定长参数。可分为:
- 1)不定长元组参数:以值的元组的形式传入的参数
- 2)不定长关键字参数:以键值对的方式传入的参数
# 2.1 示例:不定长元组参数*args
不定长元组参数,*
符号用来收集和分配参数,可用来收集函数的入参和多余的返回值
例如通过*
的分配参数功能,上述函数add
,可按如下方式调用:
>>>a = [12,98]
>>>add(*a)
x=12
y=98
110
使用*
收集参数即可实现不定长参数,重新定义add
函数即可实现任意数字的相加。
def add(*args):
res = 0
for idx, num in enumerate(args):
print(f"args[{idx}]: {num}")
res += num
print(res)
return res, res-1, res-2
调用方式如下:
>>>res, *tmp = add(1)
args[0]: 1
1
res:0
tmp:[0, -1]
>>>add(1,2)
args[0]: 1
args[1]: 2
3
>>>add(1,4,2)
args[0]: 1
args[1]: 4
args[2]: 2
7
# 2.2 示例:不定长关键字参数**kargs
不定长关键字参数**kargs
,**
可将参数展开成字典型。通过**
符号,可按如下方式调用section 1
中的add
函数:
>>> params = {"y":15,"x":12}
>>> add(**params)
x=12
y=15
27
定义函数时可以使用**
来接收不确定个数的关键字参数。
def add(**kargs):
res = 0
for k,v in kargs.items():
print(f"kargs[{k}]:{v}")
res += v
return res
调用方式如下:
>>>add(a=1)
kargs[a]:1
1
>>>add(x=1,y=2)
kargs[x]:1
kargs[y]:2
3
>>>add(x=1,y=2,z=4)
kargs[x]:1
kargs[y]:2
kargs[z]:4
7
# 3.必备参数/可选参数/不定长参数混用
必备参数、可选参数、不定长参数可以混合使用,如:
def add(x, y, z=10, *args, a, b, **kargs):
print(x, y, z, args, a, b, kargs)
res = x + y + z + a + b
for idx, num in enumerate(args):
print(f"args[{idx}]: {num}")
res += num
for k,v in kargs.items():
print(f"kargs[{k}]:{v}")
res += v
return res
>>> add(1, 2, 12, 5, 8, 10, a=20, b=30, yy=202)
1 2 12 (5, 8, 10) 20 30 {'yy': 202}
args[0]: 5
args[1]: 8
args[2]: 10
kargs[yy]:202
290
以上,*args
后面的a
,b
是命名关键字参数,必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错。若函数中没有使用*args
时想使用命名关键字参数时,需在其前一个参数使用一个*
符号,如,
def add(x, y, z=10, *, a, b):
return x + y + z + a + b
如上定义,函数调用时必须使用add(1,2,3,a=xxx, b=xx)
的形式,否则报错,如:
# right
>>>add(1,2,3,a=4,b=5)
15
# error
>>>add(1,2,3,a=4,5)
SyntaxError: positional argument follows keyword argument
注意事项:
1.必备参数需定义在可选参数前
2.命名关键字参数与位置参数不同,必须传入关键字
# 4.*
和**
的其他用法
*
连接数组
>>> a = [1,2,3]
>>> b = [4,5,*a]
[4,5,1,2,3]
**
连接字典
>>> a = {"x":1, "y":2}
>>> b = dict(z=12, **a)
{"x":1, "y":2, "z":12}
# 5.函数参数定义中的/
和*
在函数定义声明参数中使用/
和*
符号,不表示参数本身,仅是类似助记符号,/
前面的参数仅能以位置参数的形式传递,*
后的参数仅能以关键字参数的形式传递,/
和*
之间的参数既能以位置参数又能以关键字参数传递。
def add(a, b, /, c=1, d=2, *, e=12):
print(a + b + c + d + e)
add(1, 2, 3, 4, 5) # 报错
"""
TypeError Traceback (most recent call last)
Input In [47], in <cell line: 4>()
1 def add(a, b, /, c=1, d=2, *, e=12):
2 print(a + b + c + d + e)
----> 4 add(1, 2, 3, 4, 5)
TypeError: add() takes from 2 to 4 positional arguments but 5 were given
"""
add(1, 2, 3, 4, e = 5) # correct 15
add(1, 2, 3, d = 4, e = 5) # correct 15
# 参考资料
- 1.https://docs.pythontab.com/interpy/args_kwargs/Using_args_and_kwargs_to_call_function/ (opens new window)
- 2.https://www.liaoxuefeng.com/wiki/1016959663602400/1017261630425888 (opens new window)
- 3.https://clouds.eos.ubc.ca/~phil/docs/problem_solving/07-Functions-and-Modules/07.07-Positional-and-Keyword-Arguments.html (opens new window)
- 4.https://www.cnblogs.com/xueweisuoyong/p/11891310.html (opens new window)