Python 中的 *args
和 **kwargs
是在函数定义中使用的特殊语法,它们允许函数接受不定数量的参数。它们是处理函数灵活性的强大工具。
1. *args
(星号 args)
*args
允许函数接受任意数量的位置参数(positional arguments)。当你在函数定义中使用 *args
时,它会将所有传递给函数的额外位置参数收集到一个元组(tuple) 中。
-
args
只是一个约定俗成的名字:你可以用任何其他合法的变量名代替args
(例如*numbers
),但args
是最常用的惯例。 -
星号
*
是关键:它告诉 Python 将所有额外的位置参数打包成一个元组。
示例:
def sum_all_numbers(*args):
"""
这个函数可以接受任意数量的数字参数,并返回它们的和。
"""
print(f"args type: {type(args)}")
print(f"args content: {args}")
total = 0
for num in args:
total += num
return total
print(sum_all_numbers(1, 2))
print(sum_all_numbers(1, 2, 3, 4, 5))
print(sum_all_numbers()) # 也可以不传参数
输出:
args type: <class 'tuple'>
args content: (1, 2)
3
args type: <class 'tuple'>
args content: (1, 2, 3, 4, 5)
15
args type: <class 'tuple'>
args content: ()
0
2. **kwargs
(双星号 kwargs)
**kwargs
允许函数接受任意数量的关键字参数(keyword arguments)。当你在函数定义中使用 **kwargs
时,它会将所有传递给函数的额外关键字参数收集到一个字典(dictionary) 中。
-
kwargs
也是一个约定俗成的名字:你可以用任何其他合法的变量名代替kwargs
(例如**config
),但kwargs
是最常用的惯例。 -
双星号
**
是关键:它告诉 Python 将所有额外的关键字参数打包成一个字典。
示例:
def print_user_info(**kwargs):
"""
这个函数可以接受任意数量的关键字参数,并打印用户信息。
"""
print(f"kwargs type: {type(kwargs)}")
print(f"kwargs content: {kwargs}")
if "name" in kwargs:
print(f"Name: {kwargs['name']}")
if "age" in kwargs:
print(f"Age: {kwargs['age']}")
if "city" in kwargs:
print(f"City: {kwargs['city']}")
print("-" * 20)
print_user_info(name="Alice", age=30)
print_user_info(occupation="Engineer", country="USA")
print_user_info() # 也可以不传参数
输出:
kwargs type: <class 'dict'>
kwargs content: {'name': 'Alice', 'age': 30}
Name: Alice
Age: 30
--------------------
kwargs type: <class 'dict'>
kwargs content: {'occupation': 'Engineer', 'country': 'USA'}
--------------------
kwargs type: <class 'dict'>
kwargs content: {}
--------------------
3. 同时使用 *args
和 **kwargs
你可以在同一个函数定义中同时使用 *args
和 **kwargs
。在这种情况下,它们必须遵循特定的顺序:普通参数 -> *args
-> **kwargs
。
def describe_item(item_name, *features, **details):
"""
描述一个物品,包括其名称、任意数量的特征和任意数量的额外细节。
"""
print(f"Item: {item_name}")
if features:
print(f"Features: {features}")
if details:
print(f"Details:")
for key, value in details.items():
print(f" {key}: {value}")
print("-" * 30)
describe_item("Laptop", "lightweight", "fast", manufacturer="Dell", price=1200)
describe_item("Book", "paperback")
describe_item("Bottle")
输出:
Item: Laptop
Features: ('lightweight', 'fast')
Details:
manufacturer: Dell
price: 1200
------------------------------
Item: Book
Features: ('paperback',)
------------------------------
Item: Bottle
------------------------------
4. 解包(Unpacking)参数
*
和 **
不仅用于收集参数,还可以用于解包(unpacking) 序列和字典,以便将它们作为参数传递给函数。
-
*
解包可迭代对象:将列表或元组中的元素作为单独的位置参数传递。 -
**
解包字典:将字典中的键值对作为单独的关键字参数传递。
示例:
def my_function(a, b, c):
print(f"a: {a}, b: {b}, c: {c}")
# 使用 * 解包列表/元组
my_list = [1, 2, 3]
my_function(*my_list) # 等同于 my_function(1, 2, 3)
my_tuple = (4, 5, 6)
my_function(*my_tuple) # 等同于 my_function(4, 5, 6)
# 使用 ** 解包字典
my_dict = {'a': 7, 'b': 8, 'c': 9}
my_function(**my_dict) # 等同于 my_function(a=7, b=8, c=9)
# 同时解包
def complex_function(x, y, *args, **kwargs):
print(f"x: {x}, y: {y}")
print(f"args: {args}")
print(f"kwargs: {kwargs}")
data_args = [10, 20, 30]
data_kwargs = {'key1': 'value1', 'key2': 'value2'}
complex_function(5, 6, *data_args, **data_kwargs)
输出:
a: 1, b: 2, c: 3
a: 4, b: 5, c: 6
a: 7, b: 8, c: 9
x: 5, y: 6
args: (10, 20, 30)
kwargs: {'key1': 'value1', 'key2': 'value2'}
总结
-
*args
: 收集所有额外的位置参数到一个元组中。 -
**kwargs
: 收集所有额外的关键字参数到一个字典中。 - 它们使得函数能够处理不定数量的输入,极大地增强了函数的灵活性和通用性。
- 它们也可以用于解包可迭代对象(
*
)和字典(**
),将它们的元素作为参数传递给函数。
理解并熟练使用 *args
和 **kwargs
是编写更灵活、更通用的 Python 函数的关键。