默认参数

调用时不传就用默认值:

def greet(name, greeting="你好"):
    return f"{greeting}, {name}"

greet("WadeLy")                  # '你好, WadeLy'
greet("WadeLy", "嗨")            # '嗨, WadeLy'
greet("WadeLy", greeting="嗨")   # 关键字传参,更清晰

默认参数必须在普通参数后面

def f(a=1, b):    # SyntaxError
    pass

关键字参数 vs 位置参数

def order(food, size, spicy):
    return f"{size} {food} {'辣' if spicy else '不辣'}"

# 位置传参
order("拉面", "大", True)

# 关键字传参(顺序无所谓,可读性更好)
order(food="拉面", size="大", spicy=True)
order(spicy=True, food="拉面", size="大")    # 也对

# 混用:位置在前,关键字在后
order("拉面", size="大", spicy=True)

*args:任意个位置参数

def total(*nums):
    return sum(nums)

total(1, 2, 3)           # 6
total(1, 2, 3, 4, 5)     # 15

*nums 把所有位置参数收集成元组。

**kwargs:任意个关键字参数

def show(**info):
    for k, v in info.items():
        print(f"{k}: {v}")

show(name="WadeLy", age=30, city="深圳")
# name: WadeLy
# age: 30
# city: 深圳

**info 收集成字典。

全部组合(顺序固定)

def f(a, b, *args, c=10, **kwargs):
    print(a, b, args, c, kwargs)

f(1, 2, 3, 4, c=20, x=100, y=200)
# 1 2 (3, 4) 20 {'x': 100, 'y': 200}

顺序:普通参数 → *args → 默认参数 → **kwargs

拆包传参

nums = [1, 2, 3]
def add(a, b, c):
    return a + b + c

add(*nums)             # 等价 add(1, 2, 3) → 6

config = {"a": 1, "b": 2, "c": 3}
add(**config)          # 等价 add(a=1, b=2, c=3) → 6

* 拆列表/元组,** 拆字典。

默认参数的坑

不要用可变对象做默认值

def append_item(item, lst=[]):    # 坑!
    lst.append(item)
    return lst

append_item(1)    # [1]
append_item(2)    # [1, 2]!?  默认值被共享了

# 正确写法
def append_item(item, lst=None):
    if lst is None:
        lst = []
    lst.append(item)
    return lst

下一篇讲作用域——变量从哪里来、能到哪里去。