python的方法的参数除了可以使用标识符,还可以使用*和**作为参数,这些符号在python中常用于处理可变数量的参数(也称为“可变参数”或“星号参数”)。
注意:*通常与变量名结合使用,如*args(表示任意数量的位置参数);**通常如**kwargs(表示任意数量的关键字参数)。这些名字是惯例,不是必须的,可以用其他名字替换。
1.*的用法(可变位置参数)
- 在函数定义中:
*用于收集任意数量的位置参数(positional arguments),这些参数会被打包成一个元组(tuple)。这允许函数接受不定数量的参数,而无需预先指定。- 语法:
def func(固定参数, *args): ... *args收集所有多余的位置参数。- 位置:
*args必须在固定位置参数之后,在**kwargs之前(如果有)。
- 语法:
- 在函数调用中:
*用于“展开”(unpack)一个可迭代对象(如列表、元组),将其元素作为位置参数传入函数。- 语法:
func(*iterable) - 这相当于将iterable的每个元素逐个作为位置参数传递。
- 语法:
示例(定义和调用结合)
# 函数定义中使用 *
def sum_numbers(*args):
total = 0
for num in args: # args是一个元组
total += num
return total
# 调用:直接传入多个位置参数
print(sum_numbers(1, 2, 3)) # 输出: 6 (args = (1, 2, 3))
# 函数调用中使用 * 展开
numbers = [4, 5, 6] # 列表
print(sum_numbers(*numbers)) # 输出: 15 (相当于 sum_numbers(4, 5, 6))2.**的用法(可变关键字参数)
- 在函数定义中:
**用于收集任意数量的关键字参数(keyword arguments),这些参数会被打包成一个字典(dict)。键是参数名,值是参数值。- 语法:
def func(固定参数, **kwargs): ... **kwargs收集所有多余的关键字参数。- 位置:
**kwargs必须在所有其他参数之后(包括*args)。
- 语法:
- 在函数调用中:
**用于“展开”一个字典,将其键值对作为关键字参数传入函数。- 语法:
func(**dictionary) - 这相当于将字典的每个键值对作为
key=value形式传递。
- 语法:
示例(定义和调用结合)
# 函数定义中使用 **
def print_info(**kwargs):
for key, value in kwargs.items(): # kwargs是一个字典
print(f"{key}: {value}")
# 调用:直接传入多个关键字参数
print_info(name="alice", age=30, city="new york")
# 输出:
# name: alice
# age: 30
# city: new york
# 函数调用中使用 ** 展开
info = {"name": "bob", "age": 25, "city": "london"}
print_info(**info) # 相当于 print_info(name="bob", age=25, city="london")
# 输出同上3. 同时使用*和**
- 在函数定义中:可以同时使用
*args和**kwargs,以处理不定数量的位置参数和关键字参数。- 顺序必须是:固定位置参数 →
*args→ 固定关键字参数 →**kwargs。 - 这允许函数非常灵活,能接受各种参数组合。
- 顺序必须是:固定位置参数 →
- 在函数调用中:可以同时使用
*展开位置参数和**展开关键字参数。- 语法:
func(*iterable, **dictionary) - 注意:展开的位置参数必须在关键字参数之前(python的调用规则)。
- 语法:
- 原理:在定义中,
*和**允许函数“捕获”额外参数;在调用中,它们允许“注入”参数。这常用于装饰器、api函数或需要转发参数的场景。
详细代码示例:同时使用*和**(定义和调用)
# 示例1: 函数定义中同时使用 * 和 **
def flexible_func(a, b, *args, **kwargs):
print(f"固定位置参数: a={a}, b={b}")
print(f"可变位置参数 (*args): {args}") # 元组
print(f"可变关键字参数 (**kwargs): {kwargs}") # 字典
# 可以进一步处理args和kwargs
total = a + b + sum(args)
for key, value in kwargs.items():
print(f"额外信息: {key} = {value}")
return total
# 调用方式1: 直接传入参数
result = flexible_func(1, 2, 3, 4, name="alice", age=30)
print(f"结果: {result}")
# 输出:
# 固定位置参数: a=1, b=2
# 可变位置参数 (*args): (3, 4)
# 可变关键字参数 (**kwargs): {'name': 'alice', 'age': 30}
# 额外信息: name = alice
# 额外信息: age = 30
# 结果: 10 (1+2+3+4)
# 调用方式2: 使用 * 和 ** 展开传入
pos_args = [1, 2, 3, 4] # 列表作为位置参数
kw_args = {"name": "bob", "age": 25} # 字典作为关键字参数
result = flexible_func(*pos_args, **kw_args) # 相当于 flexible_func(1, 2, 3, 4, name="bob", age=25)
print(f"结果: {result}")
# 输出同上,但 kwargs={'name': 'bob', 'age': 25},结果仍为10
# 示例2: 更复杂的场景(参数转发)
def wrapper_func(*args, **kwargs):
# 将所有参数转发给另一个函数
return flexible_func(*args, **kwargs)
# 调用wrapper_func,它会转发
result = wrapper_func(5, 6, 7, city="tokyo", country="japan")
print(f"结果: {result}")
# 输出:
# 固定位置参数: a=5, b=6
# 可变位置参数 (*args): (7,)
# 可变关键字参数 (**kwargs): {'city': 'tokyo', 'country': 'japan'}
# 额外信息: city = tokyo
# 额外信息: country = japan
# 结果: 18 (5+6+7)另一个综合示例:混合固定参数和可变参数
def order_food(main_dish, *sides, **options):
print(f"主菜: {main_dish}")
print(f"配菜: {sides}")
print(f"选项: {options}")
# 直接调用
order_food("pizza", "fries", "salad", size="large", drink="coke")
# 输出:
# 主菜: pizza
# 配菜: ('fries', 'salad')
# 选项: {'size': 'large', 'drink': 'coke'}
# 展开调用
sides_list = ["fries", "salad"]
options_dict = {"size": "large", "drink": "coke"}
order_food("pizza", *sides_list, **options_dict) # 同上输出注意事项
- 顺序规则:
- 定义时:位置参数 →
*args→ 关键字参数 →**kwargs。 - 调用时:位置参数(包括
*展开)必须在关键字参数(包括**展开)之前。
- 定义时:位置参数 →
- python版本差异:python 3.5+ 支持更多灵活性,如仅位置参数(
/)和仅关键字参数(*),但基本用法不变。 - 常见错误:
- 如果
*args接收到关键字参数,会报错(typeerror)。 - 展开时,确保iterable是可迭代的,dictionary的键必须是字符串。
- 不要在定义中重复使用
*或**(如两个*args)。
- 如果
- 实际应用:常用于库函数(如
print(*objects, sep=' '))、装饰器或需要处理未知参数的函数。
到此这篇关于python *和**做参数的用法的文章就介绍到这了,更多相关python *和**内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论