站在参数列表:收集
def log(*items, **fields):
print(items) # 元组
print(fields) # 字典多出来的实参 → 两个容器
*items 收额外位置实参;**fields 收没有匹配到显式参数的关键字实参。同一个星号站在不同位置,动作正好相反:定义参数时把多出来的值收拢;调用函数时把容器里的值拆开。选几组零件,看看接收端最终拿到什么。
先展开调用零件,再按函数签名绑定。
读代码时先问一句:“这是函数定义,还是函数调用?”位置一确定,星号方向就清楚了。接收方的变量名并不强制叫 args 或 kwargs,那只是最常见的约定。
def log(*items, **fields):
print(items) # 元组
print(fields) # 字典*items 收额外位置实参;**fields 收没有匹配到显式参数的关键字实参。items = ["警告", "磁盘"]
fields = {"level": 2}
log(*items, **fields)* 的对象必须可迭代;** 的对象必须是映射,并且交给函数调用的键必须是字符串。* 与 **,阅读时按从左到右组合。format=...,又从 ** 展开出 format,会在调用阶段触发 TypeError,不会采用“后者覆盖前者”。