11·模块三:函数入门

函数参数(位置、关键字、默认值)

functionsargumentskwargs

第11课:函数参数(位置、关键字、默认值)

学习目标

完成本课学习后,你将能够:

  1. 清晰区分位置参数、关键字参数和默认值参数。
  2. 掌握在函数定义和调用时正确使用这三种参数类型。
  3. 理解并遵守关键字参数必须在位置参数之后的规则。
  4. 能够运用所学的参数知识,编写灵活、可读性更强的函数。

核心概念

在上一课中,我们学会了如何定义和调用一个基础函数。当一个函数需要"原材料"来工作时,这些原材料就是参数。给函数传递参数有几种不同的方式,就像点菜一样:

  • 位置参数(Positional Arguments):就像你按菜单顺序点菜。"来一份宫保鸡丁,一碗米饭"。顺序不能错,第一个是宫保鸡丁,第二个是米饭。在函数调用时,参数的值会按顺序依次赋给函数定义中的参数变量。
  • 关键字参数(Keyword Arguments):就像你明确说出菜名和你的特殊要求。"米饭要一碗,宫保鸡丁少放辣"。你通过"关键字"(如 米饭=宫保鸡丁=)明确指定了每个参数的值,顺序就无所谓了。这让代码意图更清晰。
  • 默认值参数(Default Arguments):就像菜单上写着"推荐做法:微辣"。如果你不特别说明,厨师就按默认的"微辣"来做。在函数定义时,你可以为某些参数预设一个默认值。调用时,如果提供了该参数的值,就用提供的;否则,就用默认值。

代码示例

让我们通过一个制作三明治的函数来理解这些概念。

# 定义一个函数:制作三明治
def make_sandwich(bread, filling, sauce='mayo'):
    """
    根据给定的食材制作一个三明治。
    :param bread: 面包类型 (位置参数)
    :param filling: 馅料 (位置参数)
    :param sauce: 酱料,默认为蛋黄酱 (默认值参数)
    """
    print(f"正在制作三明治:")
    print(f"  面包:{bread}")
    print(f" 馅料:{filling}")
    print(f" 酱料:{sauce}")
    print("美味的三明治做好了!\n")

# 1. 使用位置参数调用 (顺序很重要: bread, filling, sauce)
print("--- 使用位置参数 ---")
make_sandwich('全麦面包', '金枪鱼', '千岛酱')
make_sandwich('白面包', '火腿')  # 使用默认酱料 (mayo)

# 2. 使用关键字参数调用 (顺序不重要,名称要正确)
print("--- 使用关键字参数 ---")
make_sandwich(filling='生菜和番茄', bread='黑麦面包', sauce='蜂蜜芥末')
make_sandwich(sauce='番茄酱', filling='烤牛肉', bread='法棍')  # 顺序完全不同

# 3. 混合使用位置参数和关键字参数 (关键规则:位置参数必须在关键字参数之前!)
print("--- 混合使用参数 (正确) ---")
make_sandwich('全麦面包', filling='鸡蛋', sauce='蛋黄酱')
# 第一个参数用位置,后两个用关键字。这是允许的。

# 4. 错误示例:位置参数不能在关键字参数之后
# print("--- 混合使用参数 (错误) ---")
# make_sandwich(bread='全麦面包', '金枪鱼', '千岛酱')  # 这行会报错:SyntaxError

运行结果:

--- 使用位置参数 ---
正在制作三明治:
  面包:全麦面包
  馅料:金枪鱼
  酱料:千岛酱
美味的三明治做好了!

正在制作三明治:
  面包:白面包
  馅料:火腿
  酱料:mayo
美味的三明治做好了!

--- 使用关键字参数 ---
正在制作三明治:
  面包:黑麦面包
  馅料:生菜和番茄
  酱料:蜂蜜芥末
美味的三明治做好了!

正在制作三明治:
  面包:法棍
  馅料:烤牛肉
  酱料:番茄酱
美味的三明治做好了!

--- 混合使用参数 (正确) ---
正在制作三明治:
  面包:全麦面包
  馅料:鸡蛋
  酱料:蛋黄酱
美味的三明治做好了!

实践练习

  1. 基础练习:定义一个函数 greet_user,它需要两个参数:name(姓名)和 message(问候语,如"你好"、"早上好")。使用位置参数和关键字参数分别调用该函数,观察输出。
  2. 默认值练习:修改上面的 greet_user 函数,给 message 参数一个默认值 '你好'。然后测试以下调用:
    • greet_user('小明')
    • greet_user('小红', '晚上好')
    • greet_user(name='小华', message='下午好')
  3. 综合应用:编写一个函数 calculate_total,它接收三个参数:price(单价)、quantity(数量,默认值为1)、discount(折扣率,默认值为1.0,即无折扣)。函数应计算并打印总价。测试用例:单价100,数量3,折扣0.9;单价50,数量1(使用默认)。

常见错误

  1. 遗漏必需参数:调用函数时,没有为所有没有默认值的参数提供值。
    def say_hello(name, greeting):
        print(f"{greeting}, {name}!")
    # say_hello()  # TypeError: say_hello() missing 2 required positional arguments: 'name' and 'greeting'
    
  2. 位置参数在关键字参数之后:这是Python的语法规则,顺序必须严格遵守。
    def func(a, b):
        pass
    # func(a=1, 2)  # SyntaxError: positional argument follows keyword argument
    
  3. 使用可变对象作为默认值:这是一个经典陷阱。不要使用列表、字典等可变对象作为默认参数,因为它们只在函数定义时创建一次,后续调用会共享同一个对象。
    def bad_append(item, my_list=[]):
        my_list.append(item)
        print(my_list)
    
    bad_append(1)  # 输出 [1]
    bad_append(2)  # 输出 [1, 2],而不是期望的 [2]
    # 正确做法是使用 None 作为默认值,在函数内部判断并初始化。
    def good_append(item, my_list=None):
        if my_list is None:
            my_list = []
        my_list.append(item)
        print(my_list)
    

小结

本课我们深入学习了函数的三种参数类型:

  • 位置参数:最基本的参数,按顺序传递,数量必须匹配。
  • 关键字参数:通过 键=值 的形式传递,顺序无关,极大提高了代码可读性。
  • 默认值参数:在定义函数时为参数预设值,使得函数调用更灵活,可以省略具有合理默认值的参数。

关键规则:在函数调用时,所有的位置参数必须出现在关键字参数之前。默认值参数最好放在参数列表的末尾。

理解并熟练运用这些参数类型,将使你能够编写出接口清晰、易于使用和维护的函数,这是迈向更高级编程技巧的重要一步。下一课,我们将学习函数的"输出"——返回值,以及至关重要的变量作用域概念。

练习编辑器

python
Loading...

继续学习

完成本课后,建议继续学习下一课「返回值与作用域(LEGB)」 以巩固所学知识。