divmod(20, 8) #输出:(2, 4)
t = (20, 8)
divmod(*t) #输出:(2, 4)
定义函数时可以使用*args捕获余下的任意数量的参数,这是Python的一个经典特性。
a, b,*rest = range(5)
a, b, rest #输出: (0, 1, [2, 3, 4])
a, b,*rest = range(3)
a, b, rest #输出: (0, 1, [2])
a, b,*rest = range(2)
a, b, rest #输出: (0, 1, [])
并行赋值时,*前缀只能应用到一个变量上,不过可以是任何位置上的变量。
a, *body, c, d = range(5)
a, b, rest #输出: (0, [1, 2], 3, 4)
*head, b, c, d = range(5)
head, b, c, d #输出: ([0, 1], 2, 3, 4)
def fun(a, b, c, d, *rest):
return a, b, c, d, rest
fun(*[1, 2], 3, *range(4, 7)) #输出:(1, 2, 3, 4, (5, 6))
*range(4), 4 #输出:(0, 1, 2, 3, 4)
[*range(4), 4] #输出:[0, 1, 2, 3, 4]
{*range(4), 4, *(5, 6, 7)} #输出:{0, 1, 2, 3, 4, 5, 6, 7}
首先,调用函数时,不止一个参数可以使用**。但是,所有键都要是字符串,而且在所有参数中是唯一的(因为关键字参数不可重复)。
def dump(**kwargs):
return kwargs
dump(**{'x': 1}, 'y': 2, **{'z': 3}) #输出:{'x': 1, 'y': 2, 'z': 3}
其次,**可在dict字面量中使用,同样可以多次使用。
{'a': 0,**{'x': 1}, 'y': 2, **{'z': 3, 'x': 4}} #输出:{'a':0, 'x': 4, 'y': 2, 'z': 3}
在函数定义中,单独使用 * 可以强制后续参数必须通过关键字传入。
def greet(name, *, message="Hello"):
print(f"{message}, {name}!")
greet("Alice") # 输出 "Hello, Alice!"
greet("Bob", message="Hi") # 正确,输出 "Hi, Bob!"
greet("Charlie", "Hey") # 报错:位置参数不允许
*_ 匹配任意数量的项,而且不绑定变量。
match record:
'''
匹配任何以字符串开头,
以嵌套两个浮点数的序列结尾的序列。
'''
case [str(name), *_, (float(lat), float(lon))]:
pass
场景 | 示例 | 说明 |
---|---|---|
乘法/重复 | 3 * 4 或 [1,2] * 3 | 数值乘法或序列重复 |
函数参数(*args) | def func(*args): … | 接收任意位置参数 |
解包参数 | func(*[1,2,3]) | 将列表解包为位置参数 |
强制关键字参数 | def func(a, *, b): … | b 必须通过关键字传入 |
扩展解包 | a, *b = [1,2,3] | 将剩余元素赋值给 b(列表) |
通配符导入 | from math import * | 导入模块所有公共名称 |
映射拆包 | def dump(**kwargs): dump(**{‘x’: 1}, ‘y’: 2, **{‘z’: 3}) | **可在dict字面量中使用,同样可以多次使用。 |
match/case语句中使用 *_ | case [str(name), *_, (float(lat), float(lon))]: | 匹配任何以字符串开头,以嵌套两个浮点数的序列结尾的序列。 |
根据具体场景选择合适用法,注意避免滥用通配符导入和过度依赖可变参数以提高代码可读性