# 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后面的ab是命名关键字参数,必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错。若函数中没有使用*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

# 参考资料

(adsbygoogle = window.adsbygoogle || []).push({});