Python中*和**在参数中的作用详解
技术背景
在Python编程中,*
和 **
操作符在函数参数处理方面具有特殊用途。它们允许函数接受任意数量的位置参数和关键字参数,这在处理不确定参数数量的情况时非常有用。同时,它们也可以用于函数调用时的参数解包操作。
实现步骤
1. 理解位置参数和关键字参数
- 位置参数:函数定义时按顺序排列的参数,调用时需按顺序传入对应的值。
1 2 3 4 5 6
| def test(a, b, c): print(a) print(b) print(c)
test(1, 2, 3)
|
- 关键字参数:函数调用时通过参数名指定参数值,不依赖参数顺序。
1 2 3 4 5 6
| def test(a=0, b=0, c=0): print(a) print(b) print(c)
test(a=1, b=2, c=3)
|
2. *
和 **
在函数调用中的使用
1 2 3 4 5 6 7
| def sum(a, b): print(a + b)
my_tuple = (1, 2) my_list = [1, 2] sum(*my_tuple) sum(*my_list)
|
1 2
| my_dict = {'a': 1, 'b': 2} sum(**my_dict)
|
3. *
和 **
在函数定义中的使用
*args
:用于接受任意数量的位置参数,这些参数会被打包成一个元组。
1 2 3 4 5 6 7
| def sum(*args): total = 0 for a in args: total += a print(total)
sum(1, 2, 3, 4)
|
**kwargs
:用于接受任意数量的关键字参数,这些参数会被打包成一个字典。
1 2 3 4 5 6 7
| def sum(**args): total = 0 for k, v in args.items(): total += v print(total)
sum(a=1, b=2, c=3, d=4)
|
4. Python 3 中的新特性
- 关键字仅参数:在
*args
之后的参数必须以关键字参数的形式传入。
1 2 3 4
| def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs): return arg, kwarg, args, kwarg2, kwargs
print(foo(1, 2, 3, 4, 5, kwarg2='kwarg2', bar='bar', baz='baz'))
|
- 仅允许关键字参数:使用单独的
*
表示后面的参数必须是关键字参数。
1 2 3 4
| def foo(arg, kwarg=None, *, kwarg2=None, **kwargs): return arg, kwarg, kwarg2, kwargs
print(foo(1, 2, kwarg2='kwarg2', foo='foo', bar='bar'))
|
核心代码
接受任意数量的位置和关键字参数
1 2 3 4 5 6 7
| def foo(*args, **kwargs): print(args) print(kwargs)
a = (1, 2, 3) b = {'aa': 11, 'bb': 22} foo(*a, **b)
|
装饰器中使用 *args
和 **kwargs
1 2 3 4 5 6 7 8 9 10 11 12 13
| import functools
def decorator(function): @functools.wraps(function) def wrapper(*args, **kwargs): preprocess() function(*args, **kwargs) postprocess() return wrapper
@decorator def foo(a, b, c, d=0, e=100): differentiating_process_foo(a, b, c, d, e)
|
最佳实践
- 使用标准命名:在使用
*
和 **
接受可变参数时,建议使用 *args
和 **kwargs
作为参数名,以遵循Python社区的约定。 - 参数顺序:在函数定义中,参数顺序通常为:普通参数、
*args
、关键字仅参数、**kwargs
。 - 代码复用:在编写装饰器或需要处理不同参数组合的函数时,使用
*args
和 **kwargs
可以提高代码的复用性。
常见问题
**
只能用于字典:**
操作符专门用于解包字典,如果传入非字典对象会引发错误。- 参数重复问题:不能对非可选参数进行重复赋值,否则会引发错误。
**
必须在 *
之后:在函数定义中,如果同时使用 *args
和 **kwargs
,**kwargs
必须放在 *args
之后。