Python中*和**参数的作用解析

Python中*和**参数的作用解析

技术背景

在Python编程中,函数参数的灵活性至关重要。***在函数定义和调用中有着特殊的用途,它们允许函数处理可变数量的参数,极大地增强了函数的通用性和灵活性。

实现步骤

1. *args的使用

在函数定义中,*args用于接收任意数量的位置参数,并将这些参数打包成一个元组。

1
2
3
4
5
6
7
8
9
10
11
def foo(*args):
for a in args:
print(a)

foo(1)
# 输出: 1
foo(1, 2, 3)
# 输出:
# 1
# 2
# 3

2. **kwargs的使用

**kwargs用于接收任意数量的关键字参数,并将这些参数打包成一个字典。

1
2
3
4
5
6
7
8
def bar(**kwargs):
for key, value in kwargs.items():
print(key, value)

bar(name='one', age=27)
# 输出:
# name one
# age 27

3. 混合使用

*args**kwargs可以与普通参数混合使用,以处理固定和可变参数。

1
2
3
4
5
def foo(kind, *args, bar=None, **kwargs):
print(kind, args, bar, kwargs)

foo(123, 'a', 'b', apple='red')
# 输出: 123 ('a', 'b') None {'apple': 'red'}

4. 参数解包

在函数调用时,***可以用于解包参数。*用于解包列表或元组,**用于解包字典。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def foo(x, y, z):
print("x=" + str(x))
print("y=" + str(y))
print("z=" + str(z))

mylist = [1, 2, 3]
foo(*mylist)
# 输出:
# x=1
# y=2
# z=3

mydict = {'x': 1, 'y': 2, 'z': 3}
foo(**mydict)
# 输出:
# x=1
# y=2
# z=3

5. Python 3的新特性

  • 扩展可迭代解包:在Python 3中,*可以用于赋值语句的左侧,将序列解包。
1
2
3
first, *rest = [1, 2, 3, 4]
print(first) # 输出: 1
print(rest) # 输出: [2, 3, 4]
  • 强制关键字参数:使用*可以强制后面的参数必须以关键字参数的形式传递。
1
2
3
4
5
6
7
def func(arg1, arg2, *, kwarg1, kwarg2):
pass

# 正确调用
func(1, 2, kwarg1=3, kwarg2=4)
# 错误调用
# func(1, 2, 3, 4)

核心代码

综合示例

1
2
3
4
5
6
7
def combined_example(arg1, *args, kwarg1=None, **kwargs):
print("固定参数:", arg1)
print("位置参数元组:", args)
print("强制关键字参数:", kwarg1)
print("关键字参数字典:", kwargs)

combined_example(1, 2, 3, kwarg1=4, name='John', age=30)

最佳实践

  • 装饰器中的应用:在装饰器中使用*args**kwargs可以让装饰器适用于各种不同参数的函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import functools

def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print("装饰器前置操作")
result = func(*args, **kwargs)
print("装饰器后置操作")
return result
return wrapper

@decorator
def example_function(a, b):
return a + b

print(example_function(1, 2))
  • 类继承中的应用:在类的__init__方法中使用*args**kwargs可以方便地处理父类和子类的参数。
1
2
3
4
5
6
7
8
9
10
11
12
class BaseClass:
def __init__(self, base_param):
self.base_param = base_param

class ChildClass(BaseClass):
def __init__(self, child_param, *args, **kwargs):
self.child_param = child_param
super().__init__(*args, **kwargs)

child = ChildClass(1, 2)
print(child.child_param) # 输出: 1
print(child.base_param) # 输出: 2

常见问题

1. 字典键名不匹配

在使用**解包字典时,字典的键名必须与函数参数名一致,否则会抛出TypeError

1
2
3
4
5
6
def foo(x, y):
return x + y

mydict = {'a': 1, 'b': 2}
# 错误调用,会抛出 TypeError
# foo(**mydict)

2. 参数顺序错误

在函数定义中,参数顺序必须遵循普通参数 -> *args -> 关键字参数 -> **kwargs的顺序。

1
2
3
# 错误定义,会抛出 SyntaxError
# def wrong_order(**kwargs, *args):
# pass

3. 未使用星号解包

如果在函数调用时不使用***解包参数,参数会作为一个整体传递。

1
2
3
4
5
6
def foo(x, y):
return x + y

mylist = [1, 2]
# 错误调用,会抛出 TypeError
# foo(mylist)

Python中*和**参数的作用解析
https://119291.xyz/posts/2025-04-21.python-star-double-star-parameters-explanation/
作者
ww
发布于
2025年4月22日
许可协议