跳到主要内容

函数的参数

Python 函数参数灵活:除必选参数外,还有默认参数可变参数关键字参数命名关键字参数,可组合使用。

1. 位置参数

  • 调用时按位置顺序传入,依次赋给参数。
  • 示例:power(x, n)xn 都是位置参数;power(5, 2) → x=5, n=2。
def power(x, n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s

power(5, 2) # 25
power(5, 3) # 125

2. 默认参数

  • 定义时给参数默认值,调用时可省略,简化调用。
  • 顺序必选参数在前,默认参数在后;变化大的在前,变化小的在后(变化小的适合做默认值)。
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s

power(5) # 25,等价于 power(5, 2)
power(5, 3) # 125
  • 多默认参数:可按顺序提供,也可不按顺序时写参数名,如 enroll('Adam', 'M', city='Tianjin')

默认参数必须用不可变对象

  • :默认参数在定义时就被计算出来;若默认值是可变对象(如 L=[]),多次调用会共用同一个对象,导致“记住”上次修改。
# 错误示例
def add_end(L=[]):
L.append('END')
return L

add_end() # ['END']
add_end() # ['END', 'END'] ← 错误!
  • 正确:默认值用不可变对象,可变情况在函数内新建,如用 None
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L

add_end() # ['END']
add_end() # ['END'] ← 正确

记忆:默认参数必须指向不可变对象(str、None、数字等)。

3. 可变参数

  • 传入的个数可变(0 个到任意个);在参数前加 *,函数内收到的是一个 tuple
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum

calc(1, 2, 3) # 14
calc(1, 3, 5, 7) # 84
calc() # 0
  • 已有 list/tuple 时:在变量前加 *,把元素“展开”为可变参数传入:
nums = [1, 2, 3]
calc(*nums) # 14,等价于 calc(1, 2, 3)

记忆*args → 接收 tuple;传入时 func(1,2,3)func(*list)

4. 关键字参数

  • 传入 0 个或任意个“参数名=值”;在参数前加 **,函数内收到的是一个 dict
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)

person('Michael', 30) # other: {}
person('Bob', 35, city='Beijing') # other: {'city': 'Beijing'}
person('Adam', 45, gender='M', job='Engineer') # other: {'gender': 'M', 'job': 'Engineer'}
  • 已有 dict 时:在变量前加 **,把 key-value 作为关键字参数传入;函数内 kw拷贝,改 kw 不影响外部 dict。
extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, **extra) # other: {'city': 'Beijing', 'job': 'Engineer'}

记忆**kw → 接收 dict;传入时 func(a=1, b=2)func(**dict)

5. 命名关键字参数

  • 限制调用者只能传入指定名字的关键字参数;需要特殊分隔符 ** 后面的参数即命名关键字参数。
  • 若已有可变参数 *args,则 *args 后面的参数就是命名关键字参数,不需要再写 *
# 无可变参数:必须写 *
def person(name, age, *, city, job):
print(name, age, city, job)

# 有可变参数:*args 后的即为命名关键字
def person(name, age, *args, city, job):
print(name, age, args, city, job)

person('Jack', 24, city='Beijing', job='Engineer') # 必须写参数名
# person('Jack', 24, 'Beijing', 'Engineer') # 报错:missing keyword-only arguments
  • 命名关键字可有默认值,有默认值则可选传:def person(name, age, *, city='Beijing', job):,调用时可只传 job='Engineer'

记忆:命名关键字必须传参数名;无可变参数时定义里不能省 *,否则会被当成位置参数。

6. 参数组合与顺序

  • 定义顺序(固定):必选参数默认参数可变参数命名关键字参数关键字参数
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)

def f2(a, b, c=0, *, d, **kw):
print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
  • 调用:可用 tuple + dict 解包调用任意函数:f1(*args, **kw)f2(*args, **kw);解释器按位置和参数名自动对应。
args = (1, 2, 3, 4)
kw = {'d': 99, 'x': '#'}
f1(*args, **kw) # a=1 b=2 c=3 args=(4,) kw={'d':99,'x':'#'}

提示:不要同时用太多组合,否则接口难理解。

小结

参数类型语法函数内类型传入方式
位置参数a, b按位置
默认参数a=0可省略;默认值必须不可变对象
可变参数*argstuplefunc(1,2,3)func(*list)
命名关键字*, city, job*args, city, job必须写参数名 city=..., job=...
关键字参数**kwdictfunc(a=1)func(**dict)
  • 定义顺序:必选 → 默认 → 可变 → 命名关键字 → 关键字。
  • 默认参数:一定要用不可变对象;可变对象用 None 在函数内再赋值。
  • 命名关键字:无可变参数时不能省 *;调用时必须传参数名。

练习:把 mul(x, y) 改成可接收一个或多个数并计算乘积(可变参数)。