
让函数拥有“无限容量”的秘密武器
在Python学习中,你是否见过这样的函数定义:
deffunc(*args, **kwargs):
pass
这个看起来有点奇怪的*args和**kwargs到底是什么?为什么有些函数要这样写?今天我们就用最直观的方式,彻底搞懂这对Python中的“万能接收器”。
*args和**kwargs允许函数接收可变数量的参数,让你的代码更灵活、更通用。
*args:接收任意多个位置参数,打包成元组(tuple)**kwargs:接收任意多个关键字参数,打包成字典(dict)看这个例子:
defgreet(*args, **kwargs):
# 处理位置参数
for name in args:
print(f"Hi {name}")
# 处理关键字参数
for key, value in kwargs.items():
print(f"{key} = {value}")
# 调用时传入任意参数
greet("Ana", "Bob", age=30, city="Lisbon")
输出:
Hi Ana
Hi Bob
age = 30
city = Lisbon
发生了什么?
"Ana"和"Bob"作为位置参数,被*args收集成元组 ("Ana", "Bob")age=30和city="Lisbon"作为关键字参数,被**kwargs收集成字典 {"age": 30, "city": "Lisbon"}defshow(*args, **kwargs):
print("args:", args) # 元组
print("kwargs:", kwargs) # 字典
show(1, 2, 3, a=4, b=5)
# 输出:
# args: (1, 2, 3)
# kwargs: {'a': 4, 'b': 5}
*args把位置参数打包成元组**kwargs把关键字参数打包成字典defadd(a, b, c):
return a + b + c
numbers = [1, 2, 3]
print(add(*numbers)) # 解包列表,等价于 add(1, 2, 3)
# 输出:6
info = {"a": 4, "b": 5, "c": 6}
print(add(**info)) # 解包字典,等价于 add(a=4, b=5, c=6)
# 输出:15
*iterable解包可迭代对象为位置参数**dict解包字典为关键字参数这只是约定俗成的命名,并非语法强制:
你也可以用任何名字,关键是前面的*和**:
deffunc(*任何名字, **随便什么):
# 仍然有效
但为了代码可读性,请永远遵守约定,使用*args和**kwargs。
deftimer(func):
defwrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs) # 原封不动传递参数
print(f"耗时:{time.time() - start}秒")
return result
return wrapper
@timer
defslow_add(a, b):
time.sleep(1)
return a + b
slow_add(3, 5) # 装饰器能处理任意参数的函数
classChild(Parent):
def__init__(self, *args, **kwargs):
# 先让父类处理它需要的参数
super().__init__(*args, **kwargs)
# 再处理子类特有的逻辑
self.extra = "额外属性"
defflexible_api(endpoint, *args, **kwargs):
"""通用的API调用函数,可处理不同接口的参数差异"""
print(f"调用 {endpoint}")
print(f"位置参数:{args}")
print(f"关键字参数:{kwargs}")
# 这里可以统一处理日志、缓存、重试等逻辑
defcorrect(a, b, *args, c=10, **kwargs):
pass# 正确:位置参数 → *args → 默认参数 → **kwargs
defwrong(*args, a, b):
pass# 错误:*args之后不能再有普通位置参数
# 这是错误的!*和**才是关键
deffunc(args, kwargs):# 普通的两个参数,不是可变参数
pass
# 避免这样:明明知道需要哪些参数,却用*args/**kwargs
defcalculate(*args):
# 必须手动检查args长度,容易出错
return args[0] + args[1] * args[2]
# 应该这样:明确参数意图
defcalculate(x, y, z):
return x + y * z
print()、max() | ||
*args收集位置参数为元组,**kwargs收集关键字参数为字典*和**既可用于定义函数(打包),也可用于调用函数(解包)现在,当你再看到*args, **kwargs时,你应该知道:这是一个准备拥抱任何可能性的函数。
一句话记忆:
*args收位置,**kwargs收键值,让函数容量无限大。
互动提问:你在写代码时遇到过需要可变参数的场景吗?欢迎在评论区分享你的用例!
