第八章 函数与代码复用
在程序设计中,逻辑重复是最常见的问题。当我们多次执行相似操作(如计算、输出或验证输入),若每次都重新编写代码,不仅繁琐,还容易出错。
“函数”能将完成特定任务的语句组合成独立的执行单元,实现一次定义,多次调用。它是程序结构化设计的核心,也是实现代码复用的第一步。
通过函数,我们可以将复杂问题拆解为更小的功能模块,让主程序结构更简洁,提高代码的可维护性与可测试性。
学习目标:
(1)理解函数的作用与基本语法。
(2)掌握函数的调用与返回值机制。
(3)掌握函数参数的定义与传递方式。
(4)理解局部变量、全局变量及 LEGB 原则。
(5)了解递归函数、lambda、高阶函数等进阶技巧。
(6)了解如何使用模块与包组织代码,实现项目级复用。
8.1 函数的定义与调用
函数(Function)是实现特定功能、可多次调用的独立代码模块。它可以接收输入(参数),执行运算逻辑,并返回输出(结果)。
Python 除了提供大量内置函数(如 print()、len()、range()),也允许程序员自定义函数,以便在更大的程序结构中反复使用。
8.1.1 函数的定义
Python 使用 def 自定义函数。
语法:
return 返回值(可选)• def:定义函数的关键字。
• 函数名:遵循标识符命名规则。
• 参数列表:函数接收的外部数据,可为空。
• 函数体:缩进的语句块,执行具体操作。
• return:用于返回结果,可省略。
示例:
greet()输出:
Hello, Python learner!8.1.2 函数的调用
定义函数时并不会执行,只有在调用函数时才开始执行函数体。
调用语法:
函数名(实参1, 实参2, ...)执行流程:
1、传递参数(若有);
2、执行函数体;
3、返回结果(若有)。
例 8.1 计算矩形面积
print("另一矩形面积:", area_of_rectangle(10, 2))输出:
另一矩形面积: 208.1.3 类型提示
Python 是动态类型语言,但在团队协作与大型项目中,显式的类型提示能让函数接口更清晰、减少错误。
语法结构:
...示例:
print(f"Hello, {name}")类型提示(Type Hint)属于静态提示信息,不影响函数在解释执行时的动态类型绑定。可配合工具(如 MyPy、VS Code)进行类型检查。
在教学与项目开发中,类型提示有助于提前发现类型错误,让代码更易维护。
8.2 函数的返回值
在函数定义中,可使用 return 语句结束函数执行并返回结果。
语法:
return 表达式• 若省略 return,函数默认返回 None。
• 一旦执行到 return,函数立即结束,不再执行后续语句(若有)。若函数中包含多个 return 语句,执行时只会返回第一个被触发的 return 结果。
可以有多种形式,比如单个值或多个值,甚至是函数对象。
8.2.1 函数返回值的多种形式
(1)单值返回
print(result) 输出:
25函数执行 return 后立即结束,并将表达式结果作为返回值。
(2)无返回值
print(welcome())输出:
None返回值为 None 或为空与无 return 语句时一样,函数执行后返回 None,表示没有结果值。
(3)多值返回与解包
print("商:", q, "余数:", r)输出:
商: 3 余数: 2Python 会将多个返回值打包成(tuple)返回,调用时可解包接收多个结果。
例 8.2 摄氏温度与华氏温度转换
下面编写一个完整程序,综合运用函数定义、输入输出与异常处理,实现温度换算。
print("输入错误,请输入数值!")运行示例:
对应的华氏温度为:97.7°F8.3函数参数
函数定义时的参数称为“形式参数”(形参),函数调用时的参数称为“实际参数”(实参)。
Python 的基于“对象引用”,实参与形参共享同一对象引用(但它们的变量名各自独立)。
8.3.1 必填参数与可选参数
(1)必填参数
在函数定义中,如果形参没有默认值,函数调用时必须显式(按位置或按关键字)指定对应的实参,否则解释器会报错。
# greet() # 异常,缺少必填参数(2)可选参数
在函数定义中,如果形参提供了默认值,则在函数调用时可以省略相应的实参,此时形参将直接使用默认值。
greet(name="mediaTEA") # 覆盖默认值 Hello, mediaTEA!注意:
形参默认值在函数定义阶段(即执行 def 语句时)求值一次。
若默认值是可变对象(如 list、dict),所有调用将共用同一个对象。
8.3.2 参数传递的两种方式
函数调用时,有两种基本的参数传递方式:按位置和按关键字。
(1)按位置传参
根据形参定义的先后顺序依次绑定实参。
print(add(2, 3)) # 输出 5这样的参数常被称为“位置参数”(Positional Arguments)。
提示:
按位置传参的方式最为简洁,但在参数较多时容易出错。
(2)按关键字传参
函数调用时,按照“形参名=值”的形式显式传递,可以不按形参定义的先后顺序排列。
# greet("小艾", name="小艾") # 错误,对同一参数赋值两次这样的参数常被称为“关键字参数”(Keyword Arguments)。
8.3.3 可变参数:*args 与 **kwargs
有时我们无法提前预知调用时会传入多少参数,Python 提供了两种特殊语法来接收任意数量的参数:*args 和 **kwargs。
(1)可变位置参数
在形参名前加 *(约定名称 *args),可将多余的位置实参打包为一个元组。
print(sum_all(1, 2, 3, 4)) # 10这在不确定参数个数时非常有用,如日志收集、批量处理等。
(2)可变关键字参数
在形参名前加 **(约定名称 **kwargs),可将多余的关键字实参打包为字典(dict)。
show_info(name="Alice", age=18)与 *args 不同,**kwargs 用于接收命名参数,因此结果是一个字典对象。
8.3.4 仅位置与仅关键字传参
Python 在较新的版本中引入了两个语法符号 / 与 *,用于明确指定哪些参数只能按位置或关键字传递。这些规则在标准库函数中被广泛使用(如 math.pow(x, y, /))。
(1)仅按位置传参
/ 左侧的参数只能按位置传入,不能使用关键字。
# f(a=1, b=2, c=3) # 错误,a 和 b 不能用关键字此方式常用于保证接口一致性(防止调用者乱用参数名)。
(2)仅按关键字传参
* 之后的参数必须使用关键字传递。
# f(1, 2) # 错误,b 必须使用关键字仅位置与仅关键字传参机制可避免参数名被误用或覆盖,是提高函数接口可靠性的重要特性。
8.3.5 使用参数的完整顺序
理解这些规则后,我们可以进一步明确函数中参数的完整定义顺序。
Python 要求参数顺序遵循以下规则:
位置参数 → *args → 关键字参数 → **kwargs
即:
): 掌握参数顺序有助于理解标准库中复杂函数的定义方式,例如:
print(*objects, sep=' ', end='\n', file=None)示例:
# 输出:1 4 6 (7, 8) 9 5 {'x': 10}• 在函数定义中,所有有默认值的形参必须在没有默认值的形参之后。
若定义了 *args,则其前后的参数均应遵循此规则。
• 形参中出现 * 或 *args,其前的参数只能按位置传参。
其后的参数都必须按关键字传递,有默认值的参数可以省略。
• 所有的位置参数必须在关键字参数之前。
例 8.3 成绩统计程序
设计一个函数,用于统计一组成绩的平均值和最高分,并支持灵活的输出控制。
report_scores(97, 99, 98, 95, round_digits=1, show_max=False)示例输出:
平均分:97.2这样的参数设计模式非常常见。在数据分析、图形绘制、日志记录等任务中,函数往往需要接收不定数量的输入、允许调用者通过关键字参数控制行为,具有合理的默认值以简化常规调用。
小结
本次课学习了函数的基本结构、返回值机制及多种参数形式。函数是结构化程序设计的核心工具,掌握函数的定义与调用是编写高质量 Python 程序的基础。
在下一节课中,我们将学习变量的作用域以及函数的进阶用法(如递归函数、lambda、高阶函数等)。
“点赞有美意,赞赏是鼓励”
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.