跳到主要内容

5.2 函数参数

上一节的参数是最基本的形式,这一节学几种更灵活的用法。

位置参数:按顺序对号入座

def introduce(name, age):
print(f"我叫{name},今年{age}岁")

introduce("小明", 18) # name="小明", age=18,按位置匹配
introduce(18, "小明") # ⚠️ 语法没错但逻辑错了:我叫18,今年小明岁

关键字参数:指名道姓地传

调用时写明参数名,顺序就无所谓了,可读性也更好:

introduce(age=18, name="小明") # 我叫小明,今年18岁

位置参数和关键字参数可以混用,但位置参数必须在前

introduce("小明", age=18) # ✅
introduce(name="小明", 18) # ❌ SyntaxError

默认参数:可传可不传

定义时给参数一个默认值,调用时不传就用默认的:

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

greet("小明") # 你好,小明!(用默认值)
greet("小明", "早上好") # 早上好,小明!(覆盖默认值)

其实你已经见过:print("a", "b", sep="-") 里的 sep 就是默认参数(默认是空格)。

规则:默认参数必须放在没有默认值的参数后面。

def greet(greeting="你好", name): # ❌ SyntaxError

可变参数 *args:想传几个传几个

参数名前加 *,可以接收任意多个值,函数内部拿到的是一个元组:

def add_all(*nums):
print(nums) # 是个元组
total = 0
for n in nums:
total += n
return total

print(add_all(1, 2)) # 3
print(add_all(1, 2, 3, 4)) # 10

print() 能一次打印任意多个东西,就是用了这种机制。

💡 还有个 **kwargs 接收任意多个关键字参数(得到字典),新手阶段见到认识即可,暂不深究。

新手大坑:默认参数不要用列表

def add_item(item, lst=[]): # ❌ 危险写法
lst.append(item)
return lst

print(add_item("a")) # ['a']
print(add_item("b")) # ['a', 'b'] ??怎么把上次的也带出来了

原因:默认值 [] 只在定义时创建一次,所有调用共享同一个列表。正确写法:

def add_item(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst

现在记住结论就行:默认值只用数字、字符串、None 这类不可变的东西

练习

  1. 写函数 power(base, n=2):计算 base 的 n 次方,n 默认为 2。验证 power(3) 是 9,power(2, 10) 是 1024。
  2. 写函数 make_tea(tea, size="中杯", sugar="半糖"),打印一句"一杯{size}{sugar}的{tea}"。分别用纯位置参数、纯关键字参数各调用一次。
  3. 写函数 count_max(*nums),返回传入的所有数字中的最大值。
点击查看答案
# 1
def power(base, n=2):
return base ** n

print(power(3)) # 9
print(power(2, 10)) # 1024

# 2
def make_tea(tea, size="中杯", sugar="半糖"):
print(f"一杯{size}{sugar}{tea}")

make_tea("乌龙茶", "大杯", "全糖")
make_tea(tea="乌龙茶", sugar="无糖")

# 3
def count_max(*nums):
biggest = nums[0]
for n in nums:
if n > biggest:
biggest = n
return biggest

print(count_max(3, 9, 2, 7)) # 9

本章小结

  • 位置参数按顺序,关键字参数按名字
  • 默认参数让调用更省事,但默认值别用列表/字典
  • *args 接收任意个参数

下一节:5.3 变量作用域