第6章 函数及其应用
6.1 函数基本知识

本章学习目标
通过本节学习,同学们将能够:
1.理解模块化程序设计的思想,掌握如何将复杂问题分解为多个功能模块
2.掌握函数的定义方法,包括函数名、参数列表、返回值等核心概念
3.熟练运用各种函数调用方式,包括模块内部调用、跨模块调用等
4.培养良好的编程习惯,学会编写可复用、可维护的代码

知识回顾与导入
在前面五章的学习中,我们已经掌握了Python程序设计的基础知识,包括:
·第1章:Python程序的基本结构、模块引用、缩进规则
·第2章:数据类型、变量、运算符、字符串处理
·第3章:分支程序设计(if-else语句)
·第4章:循环程序设计(for循环、while循环)
·第5章:组合数据类型(元组、列表、字典、集合)
到目前为止,我们编写的程序都是将所有代码写在一个文件中,从头到尾顺序执行。但是,当我们面对更复杂的问题时,这种方式会变得难以管理。这就引出了本章的核心内容——函数。

6.1.1 复杂程序结构与模块化
一、为什么需要模块化程序设计
1. 实际问题的复杂性
让我们通过一个具体的案例来理解模块化程序设计的必要性。
案例背景:CK学校经济管理学院需要开发一个”学生成绩管理系统”,该系统需要实现以下功能:
·录入学生信息(学号、姓名、班级)
·录入课程成绩(多门课程)
·计算每位学生的平均分
·计算每门课程的平均分
·统计各分数段人数
·按平均分排序
·输出成绩报表
如果我们将所有代码都写在一起,程序结构会变得非常混乱。让我们先看一个”反面教材”:
# 这是一个反面教材——所有代码都堆在一起# 学生成绩管理系统(非模块化版本)# 录入学生信息student_id =input("请输入学号:")student_name =input("请输入姓名:")student_class =input("请输入班级:")# 录入成绩math_score =float(input("请输入数学成绩:"))english_score =float(input("请输入英语成绩:"))python_score =float(input("请输入Python成绩:"))# 计算平均分total = math_score + english_score + python_scoreaverage = total /3# 判断等级if average >=90:grade ="优秀"elif average >=80:grade ="良好"elif average >=70:grade ="中等"elif average >=60:grade ="及格"else:grade ="不及格"# 输出结果print("="*40)print(f"学号:{student_id}")print(f"姓名:{student_name}")print(f"班级:{student_class}")print(f"数学成绩:{math_score}")print(f"英语成绩:{english_score}")print(f"Python成绩:{python_score}")print(f"平均分:{average:.2f}")print(f"等级:{grade}")print("="*40)
问题分析:
上述代码存在以下几个严重问题:
1.代码冗余:如果要处理多个学生,需要重复编写相同的代码
2.可读性差:所有功能混在一起,难以理解程序逻辑
3.维护困难:修改某个功能可能影响其他部分
4.无法复用:计算平均分、判断等级等功能无法在其他地方重用
5.调试困难:出现错误时,难以定位问题所在
2. 模块化设计的思想
模块化程序设计是一种将复杂问题分解为若干个相对独立、功能单一的模块的程序设计方法。每个模块完成一个特定的功能,模块之间通过接口进行通信。
核心思想:“分而治之” —— 将大问题分解为小问题,逐个解决。
让我们用模块化的思想重新设计上面的成绩管理系统:
# 学生成绩管理系统(模块化版本)def input_student_info():"""录入学生信息"""student_id =input("请输入学号:")student_name =input("请输入姓名:")student_class =input("请输入班级:")return student_id, student_name, student_classdef input_scores():"""录入课程成绩"""math_score =float(input("请输入数学成绩:"))english_score =float(input("请输入英语成绩:"))python_score =float(input("请输入Python成绩:"))return math_score, english_score, python_scoredef calculate_average(math, english, python):"""计算平均分"""total = math + english + pythonreturn total /3def determine_grade(average):"""判断等级"""if average >=90:return"优秀"elif average >=80:return"良好"elif average >=70:return"中等"elif average >=60:return"及格"else:return"不及格"def print_report(student_id, name, class_name, math, english, python, average, grade):"""输出成绩报表"""print("="*40)print(f"学号:{student_id}")print(f"姓名:{name}")print(f"班级:{class_name}")print(f"数学成绩:{math}")print(f"英语成绩:{english}")print(f"Python成绩:{python}")print(f"平均分:{average:.2f}")print(f"等级:{grade}")print("="*40)# 主程序def main():# 录入信息student_id, name, class_name = input_student_info()math, english, python = input_scores()# 计算与判断average = calculate_average(math, english, python)grade = determine_grade(average)# 输出报表print_report(student_id, name, class_name, math, english, python, average, grade)# 运行主程序main()
模块化版本的优势:
1.结构清晰:每个函数完成一个独立的功能,职责单一
2.易于复用:calculate_average()和determine_grade()可以在其他地方使用
3.便于维护:修改某个功能只需修改对应的函数
4.易于测试:可以单独测试每个函数是否正确
5.便于协作:团队成员可以分别开发不同的函数
二、模块化设计的层次结构
1. 语句层(Statement Level)
语句是程序的最小执行单位。我们在前面章节学过的语句包括:
·赋值语句:x = 10
·输入语句:name = input("请输入姓名:")
·输出语句:print("Hello, World!")
·分支语句:if-else
·循环语句:for、while
知识回顾:在第1章我们学习了Python程序的语句与语句块,Python通过缩进来区分语句块,这是Python的重要语法特征。
2. 函数层(Function Level)
函数是将一组相关的语句组织在一起,完成特定功能的代码块。函数是模块化设计的基本单位。
def greet(name):"""问候函数"""print(f"你好,{name}!欢迎来到CK学校!")print("祝你学习愉快!")
3. 模块层(Module Level)
模块是一个包含Python代码的文件(.py文件)。一个模块可以包含多个函数、类和变量。
知识回顾:在第1章1.3.2节,我们学习了Python程序的模块及引用,使用import语句可以引入其他模块。
# 模块示例:math_tools.pydef add(a, b):return a + bdef subtract(a, b):return a - bdef multiply(a, b):return a * bdef divide(a, b):if b !=0:return a / belse:return"除数不能为零"
4. 应用程序层(Application Level)
应用程序是由多个模块组成的完整系统。例如,一个学生管理系统可能包含以下模块:
·student_info.py:学生信息管理模块
·score_manager.py:成绩管理模块
·report_generator.py:报表生成模块
·main.py:主程序入口
三、模块化设计的基本原则
1. 单一职责原则(Single Responsibility Principle)
每个函数应该只做一件事,并且把它做好。
正确示例:
def calculate_circle_area(radius):"""计算圆的面积"""return3.14159* radius **2def print_circle_info(radius):"""输出圆的信息"""area = calculate_circle_area(radius)print(f"半径为{radius}的圆,面积是{area:.2f}")
错误示例:
def calculate_and_print(radius):"""计算并输出圆的面积(违反单一职责原则)"""area =3.14159* radius **2print(f"半径为{radius}的圆,面积是{area:.2f}")# 这个函数做了两件事:计算和输出# 如果我们只需要计算结果而不需要输出,这个函数就无法满足需求
2. 函数名要见名知意
函数名应该能够清晰地表达函数的功能。
好的命名:
def calculate_average(scores):"""计算平均分"""passdef find_max_score(scores):"""找出最高分"""passdef validate_student_id(student_id):"""验证学号格式"""pass
不好的命名:
def func1(scores):# 无法知道这个函数做什么passdef calc(s):# 太简略,不清楚计算什么passdef do_something(data):# 太模糊pass
知识回顾:在第2章2.1.2节,我们学习了标识符的命名规则。函数名也是一种标识符,需要遵循以下规则: - 只能包含字母、数字和下划线 - 不能以数字开头 - 不能使用Python关键字 - 建议使用小写字母,多个单词用下划线连接(snake_case命名法)
3. 函数应该尽可能独立
函数应该尽量减少对外部变量的依赖,通过参数接收输入,通过返回值输出结果。
好的设计:
def calculate_discount(price, discount_rate):"""计算折扣价格"""return price * (1- discount_rate)# 调用original_price =100discount =0.8final_price = calculate_discount(original_price, discount)
不好的设计:
# 不推荐:依赖全局变量price =100discount_rate =0.8def calculate_discount():"""计算折扣价格(依赖全局变量)"""return price * (1- discount_rate)# 调用final_price = calculate_discount()
四、模块化设计的实践案例
让我们通过一个完整的案例来实践模块化设计思想。
案例:CK学校数字经济专业需要统计学生的BMI指数,并给出健康建议。
"""CK学校学生BMI健康分析系统功能:计算BMI指数并给出健康建议"""def input_student_info():"""录入学生基本信息返回:姓名、身高(米)、体重(千克)"""name =input("请输入学生姓名:")height =float(input("请输入身高(米):"))weight =float(input("请输入体重(千克):"))return name, height, weightdef calculate_bmi(height, weight):"""计算BMI指数参数:height-身高(米),weight-体重(千克)返回:BMI指数"""# BMI = 体重(kg) / 身高(m)的平方bmi = weight / (height **2)return bmidef get_bmi_category(bmi):"""根据BMI值判断健康类别参数:bmi-BMI指数返回:健康类别字符串"""if bmi <18.5:return"偏瘦"elif bmi <24:return"正常"elif bmi <28:return"偏胖"else:return"肥胖"def get_health_advice(category):"""根据健康类别给出建议参数:category-健康类别返回:健康建议字符串"""advice_dict = {"偏瘦": "建议适当增加营养摄入,加强力量训练。", "正常": "恭喜!请继续保持健康的生活方式。", "偏胖": "建议控制饮食,增加有氧运动。", "肥胖": "建议咨询医生,制定科学的减重计划。"}return advice_dict[category]def print_bmi_report(name, height, weight, bmi, category, advice):"""输出BMI分析报告"""print("\n"+"="*50)print("CK学校学生BMI健康分析报告")print("="*50)print(f"学生姓名:{name}")print(f"身高:{height:.2f} 米")print(f"体重:{weight:.1f} 千克")print(f"BMI指数:{bmi:.1f}")print(f"健康类别:{category}")print(f"健康建议:{advice}")print("="*50)def main():"""主程序"""print("欢迎使用CK学校学生BMI健康分析系统")print("-"*50)# 录入信息name, height, weight = input_student_info()# 计算BMIbmi = calculate_bmi(height, weight)# 判断类别category = get_bmi_category(bmi)# 获取建议advice = get_health_advice(category)# 输出报告print_bmi_report(name, height, weight, bmi, category, advice)# 运行程序if__name__=="__main__":main()
程序运行示例:
欢迎使用CK学校学生BMI健康分析系统--------------------------------------------------请输入学生姓名:张三请输入身高(米):1.75请输入体重(千克):70==================================================CK学校学生BMI健康分析报告==================================================学生姓名:张三身高:1.75 米体重:70.0 千克BMI指数:22.9健康类别:正常健康建议:恭喜!请继续保持健康的生活方式。==================================================
五、模块化设计的优点总结
优点 | 说明 |
提高可读性 | 每个函数完成一个明确的功能,代码结构清晰 |
便于复用 | 函数可以在不同地方多次调用,避免代码重复 |
易于维护 | 修改某个功能只需修改对应的函数 |
便于测试 | 可以单独测试每个函数的正确性 |
支持团队协作 | 不同人员可以开发不同的模块 |
降低复杂度 | 将复杂问题分解为简单的小问题 |

6.1.2 函数定义
一、函数定义的基本格式
在Python中,使用def关键字来定义函数。函数定义的基本格式如下:
def 函数名(形式参数列表):"""函数文档字符串(可选)"""函数体return 返回值
语法结构图解:
def ── 函数名 ── ( ── 形式参数列表 ── ) ── : ── 换行 │││││关键字自定义固定参数列表固定符号标识符符号(可为空)│▼缩进的函数体│▼return 返回值
二、最简单的函数定义
让我们从最简单的函数开始:
def say_hello():"""输出问候语"""print("你好,欢迎来到CK学校!")# 调用函数say_hello()
输出结果:
你好,欢迎来到CK学校!
代码解析:
1.def:Python的关键字,表示要定义一个函数
2.say_hello:函数名,遵循标识符命名规则
3.():括号内没有参数,表示这是一个无参函数
4.::冒号是Python语法的固定要求,表示函数定义的开始
5."""...""":文档字符串,用于说明函数的功能(可选但推荐)
6.print(...):函数体,需要缩进
7.没有return语句,函数执行完毕后自动返回None
三、四点重要说明
说明一:关于函数名
1. 函数名的命名规则
函数名是一种标识符,必须遵循Python标识符的命名规则:
·只能包含字母(a-z, A-Z)、数字(0-9)和下划线(_)
·必须以字母或下划线开头,不能以数字开头
·不能使用Python的关键字(如def、if、for、while等)
·区分大小写(myFunc和myfunc是不同的函数名)
知识回顾:这些规则在第2章2.1.2节”标识符”中已经详细学习过。
正确示例:
def calculate_sum():# 正确:字母开头passdef _private_func():# 正确:下划线开头passdef get_student_name():# 正确:多个单词用下划线连接passdef calc2():# 正确:数字不在开头pass
错误示例:
def2calc():# 错误:数字开头passdef my-func():# 错误:包含连字符passdefclass():# 错误:使用关键字pass
2. 函数名的命名规范(推荐)
除了语法规则外,还有一些推荐的命名规范:
·使用小写字母
·多个单词之间用下划线连接(snake_case命名法)
·函数名应该能够描述函数的功能(见名知意)
·动词开头,表示这是一个动作
# 好的函数名示例def get_student_score():# 获取学生成绩passdef calculate_average():# 计算平均值passdef validate_input():# 验证输入passdef save_to_file():# 保存到文件passdef convert_to_uppercase():# 转换为大写pass
3. 函数名与变量的区别
虽然函数名和变量名都遵循相同的命名规则,但它们在使用上有明显的区别:
# 定义函数def greet():print("Hello!")# 定义变量greet_message ="Hello!"# 使用函数(需要加括号)greet()# 输出:Hello!# 使用变量(不需要括号)print(greet_message) # 输出:Hello!# 函数名本身是一个引用print(greet)# 输出:print(greet_message) # 输出:Hello!
4. 函数名可以重新赋值
在Python中,函数名可以被重新赋值,但这通常是不推荐的做法:
def greet():print("Hello!")greet()# 输出:Hello!# 不推荐:将函数名重新赋值greet ="Goodbye"print(greet)# 输出:Goodbye# 此时原来的函数已经无法通过greet访问了greet()# 错误:'str' object is not callable
说明二:关于形式参数列表
1. 什么是形式参数
形式参数(简称”形参”)是函数定义时括号内的变量名,用于接收调用函数时传入的数据。
def greet(name):# name 是形式参数print(f"你好,{name}!")greet("张三")# "张三" 是实际参数# 输出:你好,张三!
形参与实参的区别:
概念 | 说明 | 出现位置 |
形式参数(形参) | 函数定义时的变量名 | 函数定义的括号内 |
实际参数(实参) | 调用函数时传入的具体值 | 函数调用的括号内 |
2. 形参列表的多种形式
(1)无参数
def get_pi():"""返回圆周率"""return3.14159result = get_pi()print(result)# 输出:3.14159
(2)单个参数
def square(num):"""计算平方"""return num **2result = square(5)print(result)# 输出:25
(3)多个参数
def add(a, b):"""计算两数之和"""return a + bresult = add(3, 5)print(result)# 输出:8
(4)参数之间用逗号分隔
def calculate_bmi(name, height, weight):"""计算BMI指数"""bmi = weight / (height **2)print(f"{name}的BMI指数是:{bmi:.2f}")calculate_bmi("张三", 1.75, 70)# 输出:张三的BMI指数是:22.86
3. 形参的命名建议
形参的命名应该能够表达参数的含义:
# 好的命名def calculate_area(length, width):# 清楚表达是长和宽return length * widthdef create_student(name, age, grade): # 清楚表达学生属性pass# 不好的命名def calculate_area(a, b):# 不清楚a和b代表什么return a * bdef create_student(x, y, z):# 完全无法理解参数含义pass
4. 形参的作用范围
形参是局部变量,只在函数内部有效:
def test_scope(x):"""测试形参作用范围"""print(f"函数内部 x = {x}")x =100print(f"修改后 x = {x}")# 函数外部x =10print(f"调用前 x = {x}")# 输出:调用前 x = 10test_scope(50)# 输出:函数内部 x = 50# 输出:修改后 x = 100print(f"调用后 x = {x}")# 输出:调用后 x = 10
知识回顾:这里涉及变量的作用域问题,我们将在6.3节详细学习。
说明三:关于冒号
1. 冒号的作用
在Python中,冒号:用于标识一个代码块的开始。在函数定义中,冒号表示函数头的结束,函数体的开始。
def greet(name):# 函数头# ↑ 冒号后面是函数体print(f"你好,{name}!")
2. 冒号的使用场景
知识回顾:冒号在Python中有多种使用场景,我们在前面章节已经学习过:
使用场景 | 示例 | 所在章节 |
函数定义 | def func(): | 第6章 |
条件语句 | if x > 0: | 第3章 |
循环语句 | for i in range(5): | 第4章 |
循环语句 | while x < 10: | 第4章 |
字典定义 | {"name": "张三"} | 第5章 |
切片操作 | list[1:5] | 第2章、第5章 |
3. 忘记冒号的常见错误
# 错误示例:忘记冒号def greet(name)print(f"你好,{name}!")# SyntaxError: invalid syntax# 正确写法def greet(name):print(f"你好,{name}!")
4. 冒号后的缩进
冒号后面必须进行缩进,Python通过缩进来识别代码块:
def greet(name):print("第一行")# 缩进4个空格print("第二行")# 缩进4个空格if name:print(f"你好,{name}!")# 嵌套缩进print("函数外")# 不缩进,不在函数内
知识回顾:在第1章1.3.6节,我们学习了Python程序的缩进规则。Python使用缩进(通常为4个空格)来表示代码块的层次结构,这是Python的重要语法特征。
说明四:关于return语句
1. return语句的作用
return语句用于结束函数的执行,并将一个值返回给调用者。
def add(a, b):"""计算两数之和"""result = a + breturn result# 返回计算结果# 调用函数并接收返回值sum_value = add(3, 5)print(sum_value)# 输出:8
2. return语句的执行流程
当函数执行到return语句时,会立即结束函数的执行:
def check_score(score):"""检查成绩是否及格"""if score >=60:return"及格"# 执行return后,函数立即结束print("这行不会执行")# 永远不会执行else:return"不及格"result = check_score(75)print(result)# 输出:及格
3. 没有return语句的函数
如果函数没有return语句,函数执行完毕后会自动返回None:
def greet(name):"""问候函数(无返回值)"""print(f"你好,{name}!")result = greet("张三")# 输出:你好,张三!print(result)# 输出:None
4. 只有return没有返回值
def do_nothing():"""什么都不做的函数"""returnresult = do_nothing()print(result)# 输出:None
5. 返回多个值
Python允许函数返回多个值,实际上是返回一个元组:
def get_min_max(numbers):"""获取列表中的最小值和最大值"""min_val =min(numbers)max_val =max(numbers)return min_val, max_val# 返回多个值# 接收返回值minimum, maximum = get_min_max([3, 1, 4, 1, 5, 9, 2, 6])print(f"最小值:{minimum},最大值:{maximum}")# 输出:最小值:1,最大值:9# 也可以用一个变量接收result = get_min_max([3, 1, 4, 1, 5, 9, 2, 6])print(result)# 输出:(1, 9)print(type(result))# 输出:
知识回顾:元组是第5章学习的组合数据类型之一,使用圆括号定义,元素不可修改。
6. return与print的区别
这是初学者经常混淆的概念:
# 使用printdef add_print(a, b):"""计算并打印结果"""print(a + b)# 使用returndef add_return(a, b):"""计算并返回结果"""return a + b# 调用对比result1 = add_print(3, 5)# 输出:8print(f"result1 = {result1}") # 输出:result1 = Noneresult2 = add_return(3, 5)# 没有输出print(f"result2 = {result2}") # 输出:result2 = 8# return的值可以继续参与运算final = add_return(3, 5) *2print(final)# 输出:16# print的值无法继续运算final = add_print(3, 5) *2# 输出:8,然后报错
区别总结:
特性 | return | print |
作用 | 返回值给调用者 | 输出到控制台 |
是否结束函数 | 是 | 否 |
返回值能否继续使用 | 能 | 不能 |
无返回值时 | 返回None | 无返回值 |
四、函数定义程序示例
让我们通过几个完整的示例来巩固函数定义的知识。
示例1:计算圆的面积和周长
def calculate_circle_area(radius):"""计算圆的面积参数:radius - 圆的半径返回:圆的面积"""pi =3.14159area = pi * radius **2return areadef calculate_circle_circumference(radius):"""计算圆的周长参数:radius - 圆的半径返回:圆的周长"""pi =3.14159circumference =2* pi * radiusreturn circumference# 测试r =5area = calculate_circle_area(r)circumference = calculate_circle_circumference(r)print(f"半径为{r}的圆:")print(f"面积 = {area:.2f}")print(f"周长 = {circumference:.2f}")
输出结果:
半径为5的圆:面积 = 78.54周长 = 31.42
知识回顾:这里使用了算术运算符**表示幂运算,在第2章2.3.2节学习过。
示例2:判断闰年
def is_leap_year(year):"""判断是否为闰年参数:year - 年份(整数)返回:True(闰年)或 False(平年)闰年规则:1. 能被4整除但不能被100整除,或者2. 能被400整除"""if (year %4==0and year %100!=0) or (year %400==0):returnTrueelse:returnFalse# 测试test_years = [2000, 2020, 2024, 1900, 2023]for year in test_years:if is_leap_year(year):print(f"{year}年是闰年")else:print(f"{year}年是平年")
输出结果:
2000年是闰年2020年是闰年2024年是闰年1900年是平年2023年是平年
知识回顾: - 第3章学习的逻辑运算符and、or - 第2章学习的算术运算符%(取余) - 第4章学习的for循环遍历列表
示例3:统计字符串中的字符类型
def count_char_types(text):"""统计字符串中各类字符的数量参数:text - 要统计的字符串返回:包含各类字符数量的元组(大写字母, 小写字母, 数字, 其他字符)"""upper_count =0# 大写字母数量lower_count =0# 小写字母数量digit_count =0# 数字数量other_count =0# 其他字符数量for char in text:if char.isupper():upper_count +=1elif char.islower():lower_count +=1elif char.isdigit():digit_count +=1else:other_count +=1return upper_count, lower_count, digit_count, other_count# 测试test_text ="CK School 2024 @Chongqing!"upper, lower, digit, other = count_char_types(test_text)print(f"测试字符串:{test_text}")print(f"大写字母:{upper}个")print(f"小写字母:{lower}个")print(f"数字:{digit}个")print(f"其他字符:{other}个")
输出结果:
测试字符串:CK School 2024 @Chongqing!大写字母:3个小写字母:12个数字:4个其他字符:4个
知识回顾: - 第2章学习的字符串方法isupper()、islower()、isdigit() - 第4章学习的for循环遍历字符串 - 第3章学习的if-elif-else分支结构
示例4:生成斐波那契数列
def generate_fibonacci(n):"""生成前n个斐波那契数参数:n - 要生成的斐波那契数的个数返回:包含前n个斐波那契数的列表斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, ...规则:从第3项开始,每项等于前两项之和"""if n <=0:return []elif n ==1:return [1]elif n ==2:return [1, 1]fib_list = [1, 1]# 前两项for i inrange(2, n):next_value = fib_list[i-1] + fib_list[i-2]fib_list.append(next_value)return fib_list# 测试n =10fib = generate_fibonacci(n)print(f"前{n}个斐波那契数:{fib}")
输出结果:
前10个斐波那契数:[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
知识回顾: - 第5章学习的列表操作append() - 第4章学习的for循环和range()函数 - 第3章学习的if-elif-else分支结构
五、函数的返回值类型与空函数
1. 函数返回值的类型
Python是一种动态类型语言,函数的返回值可以是任意类型:
(1)返回数值类型
def add(a, b):"""返回整数"""return a + bdef divide(a, b):"""返回浮点数"""return a / bresult1 = add(3, 5)print(type(result1))#result2 = divide(7, 2)print(type(result2))#
(2)返回字符串类型
def get_greeting(name):"""返回字符串"""returnf"你好,{name}!欢迎来到CK学校!"message = get_greeting("张三")print(message)# 你好,张三!欢迎来到CK学校!print(type(message))#
(3)返回布尔类型
def is_even(number):"""判断是否为偶数"""return number %2==0print(is_even(4))# Trueprint(is_even(7))# Falseprint(type(is_even(4)))#
知识回顾:布尔类型在第2章2.2.3节学习过,只有True和False两个值。
(4)返回列表类型
def get_even_numbers(n):"""获取1到n之间的所有偶数"""even_list = []for i inrange(2, n +1, 2):even_list.append(i)return even_listresult = get_even_numbers(10)print(result)# [2, 4, 6, 8, 10]print(type(result))#
(5)返回字典类型
def create_student(name, age, score):"""创建学生信息字典"""student = {"name": name,"age": age,"score": score}return studentstudent_info = create_student("张三", 20, 85)print(student_info)# {'name': '张三', 'age': 20, 'score': 85}print(type(student_info))#
知识回顾:字典是第5章学习的组合数据类型,使用花括号定义,由键值对组成。
(6)返回元组类型
def get_min_max_avg(numbers):"""返回最小值、最大值和平均值"""min_val =min(numbers)max_val =max(numbers)avg_val =sum(numbers) /len(numbers)return (min_val, max_val, avg_val)result = get_min_max_avg([1, 2, 3, 4, 5])print(result)# (1, 5, 3.0)print(type(result))#
(7)返回多种类型
Python函数可以根据条件返回不同类型的值:
def process_value(value):"""根据输入返回不同类型的结果"""ifisinstance(value, int):return value *2# 返回整数elifisinstance(value, str):return value.upper()# 返回字符串elifisinstance(value, list):returnlen(value)# 返回整数else:returnNone# 返回Noneprint(process_value(5))# 10print(process_value("hello"))# HELLOprint(process_value([1,2,3]))# 3print(process_value(3.14))# None
2. 空函数
(1)什么是空函数
空函数是指函数体中没有任何实际执行代码的函数。在Python中,使用pass语句来定义空函数。
def empty_function():"""这是一个空函数"""pass# 调用空函数result = empty_function()print(result)# None
(2)pass语句的作用
pass是Python的一个特殊语句,它不执行任何操作,只是一个占位符。
知识回顾:在第4章4.2.3节,我们学习过pass语句,它常用于以下场景: - 定义空函数 - 定义空类 - 在循环或条件语句中占位
(3)空函数的使用场景
场景一:程序开发初期,先定义函数框架
def calculate_tax(income):"""计算个人所得税(待实现)"""pass# TODO: 实现税收计算逻辑def generate_report(data):"""生成报表(待实现)"""pass# TODO: 实现报表生成逻辑def send_email(to, subject, content):"""发送邮件(待实现)"""pass# TODO: 实现邮件发送逻辑
场景二:在分支结构中作为占位
def process_score(score):"""处理成绩"""if score >=90:print("优秀")elif score >=60:print("及格")else:pass# 暂时不处理不及格的情况
场景三:在循环中跳过某些情况
def filter_numbers(numbers):"""过滤数字,只处理正数"""for num in numbers:if num <=0:pass# 跳过非正数else:print(f"处理数字:{num}")filter_numbers([1, -2, 3, 0, 5])
输出结果:
处理数字:1处理数字:3处理数字:5
(4)省略pass会导致语法错误
# 错误示例:函数体不能为空def empty_function():# SyntaxError: expected an indented block# 正确写法def empty_function():pass
3. 函数文档字符串(Docstring)
(1)什么是文档字符串
文档字符串是位于函数定义之后、函数体之前的字符串,用于描述函数的功能、参数和返回值。
def calculate_bmi(height, weight):"""计算BMI指数参数:height: 身高(单位:米)weight: 体重(单位:千克)返回:BMI指数(浮点数)示例:>>> calculate_bmi(1.75, 70)22.857142857142858"""return weight / (height **2)
(2)访问文档字符串
使用__doc__属性可以访问函数的文档字符串:
def greet(name):"""问候函数,输出欢迎信息"""print(f"你好,{name}!")print(greet.__doc__)# 输出:问候函数,输出欢迎信息
(3)使用help()函数查看文档
def calculate_area(length, width):"""计算矩形面积参数:length: 矩形的长度width: 矩形的宽度返回:矩形的面积"""return length * widthhelp(calculate_area)
输出结果:
Help on function calculate_area in module __main__:calculate_area(length, width)计算矩形面积参数:length: 矩形的长度width: 矩形的宽度返回:矩形的面积
(4)文档字符串的编写规范
推荐使用Google风格或NumPy风格的文档字符串:
Google风格:
def get_student_info(student_id):"""根据学号获取学生信息。Args:student_id (str): 学生学号Returns:dict: 包含学生信息的字典,格式为:- name: 学生姓名- age: 学生年龄- class_name: 班级名称Raises:ValueError: 如果学号格式不正确"""pass
NumPy风格:
def calculate_average(scores):"""计算成绩的平均分。Parameters----------scores : list成绩列表,包含多个学生的成绩Returns-------float平均分Examples-------->>> calculate_average([85, 90, 78, 92])86.25"""returnsum(scores) /len(scores)

6.1.3 函数调用
一、函数引入与调用原则
1. 函数调用的基本概念
函数调用是指执行函数体内代码的过程。当调用一个函数时,程序会跳转到函数定义处执行,执行完毕后返回到调用处继续执行。
函数调用的基本语法:
函数名(实际参数列表)
函数调用的执行流程:
调用函数 ──→ 传递参数 ──→ 执行函数体 ──→ 返回结果 ──→ 继续执行后续代码
2. 函数调用的前提条件
在调用函数之前,必须确保函数已经被定义。Python是解释型语言,代码从上到下依次执行。
正确示例:
# 先定义函数def greet(name):print(f"你好,{name}!")# 后调用函数greet("张三")# 正确:函数已定义
错误示例:
# 先调用函数greet("张三")# 错误:函数尚未定义# 后定义函数def greet(name):print(f"你好,{name}!")# NameError: name 'greet' is not defined
3. 函数调用的基本原则
原则一:函数必须先定义后调用
# 正确顺序def add(a, b):return a + bresult = add(3, 5)# 正确
原则二:调用时参数数量要匹配
def add(a, b):return a + bresult = add(3)# 错误:缺少参数# TypeError: add() missing 1 required positional argument: 'b'result = add(3, 5, 7)# 错误:参数过多# TypeError: add() takes 2 positional arguments but 3 were given
原则三:参数类型要兼容
def add(a, b):return a + bresult = add(3, 5)# 正确:整数相加result = add("Hello", " World")# 正确:字符串拼接result = add(3, "5")# 错误:类型不兼容# TypeError: unsupported operand type(s) for +: 'int' and 'str'
二、模块内部的函数调用
模块内部的函数调用是最常见的调用方式,即函数定义和函数调用在同一个Python文件中。
1. 基本调用方式
# 定义函数def calculate_area(length, width):"""计算矩形面积"""return length * widthdef calculate_perimeter(length, width):"""计算矩形周长"""return2* (length + width)# 在同一模块内调用area = calculate_area(5, 3)perimeter = calculate_perimeter(5, 3)print(f"面积:{area}")# 输出:面积:15print(f"周长:{perimeter}")# 输出:周长:16
2. 函数之间的相互调用
一个函数可以调用另一个函数:
def get_score_level(score):"""获取成绩等级"""if score >=90:return"A"elif score >=80:return"B"elif score >=70:return"C"elif score >=60:return"D"else:return"E"def print_student_report(name, score):"""打印学生成绩报告"""level = get_score_level(score)# 调用另一个函数print(f"学生姓名:{name}")print(f"考试成绩:{score}")print(f"成绩等级:{level}")# 调用print_student_report("张三", 85)
输出结果:
学生姓名:张三考试成绩:85成绩等级:B
3. 函数的嵌套调用
函数可以多层嵌套调用:
def add(a, b):"""加法"""return a + bdef multiply(a, b):"""乘法"""return a * bdef calculate(a, b, c):"""计算 (a + b) * c"""# 嵌套调用:add函数的结果作为multiply函数的参数return multiply(add(a, b), c)result = calculate(2, 3, 4)print(result)# 输出:20,因为 (2 + 3) * 4 = 20
执行流程分析:
calculate(2, 3, 4)│├── multiply(add(2, 3), 4)│││├── add(2, 3) 返回 5│││└── multiply(5, 4) 返回 20│└── 返回 20
4. 函数的递归调用
函数可以调用自身,这称为递归。递归是一种重要的编程技术。
知识预告:递归函数将在6.4节详细讲解,这里先给出一个简单示例:
def factorial(n):"""计算n的阶乘(递归实现)"""if n ==1:return1else:return n * factorial(n -1)# 调用自身result = factorial(5)print(result)# 输出:120,因为 5! = 5 * 4 * 3 * 2 * 1 = 120
5. 完整案例:CK学校成绩统计系统
"""CK学校成绩统计系统演示模块内部函数调用"""def input_scores():"""录入学生成绩"""scores = []print("请输入学生成绩(输入-1结束):")whileTrue:score =float(input("成绩:"))if score ==-1:breakscores.append(score)return scoresdef calculate_total(scores):"""计算总分"""returnsum(scores)def calculate_average(scores):"""计算平均分"""iflen(scores) ==0:return0returnsum(scores) /len(scores)def get_max_score(scores):"""获取最高分"""iflen(scores) ==0:return0returnmax(scores)def get_min_score(scores):"""获取最低分"""iflen(scores) ==0:return0returnmin(scores)def get_pass_count(scores, pass_line=60):"""统计及格人数"""count =0for score in scores:if score >= pass_line:count +=1return countdef print_statistics(scores):"""输出成绩统计信息"""total = calculate_total(scores)average = calculate_average(scores)max_score = get_max_score(scores)min_score = get_min_score(scores)pass_count = get_pass_count(scores)print("\n"+"="*40)print("CK学校成绩统计报告")print("="*40)print(f"学生人数:{len(scores)}人")print(f"总分:{total}")print(f"平均分:{average:.2f}")print(f"最高分:{max_score}")print(f"最低分:{min_score}")print(f"及格人数:{pass_count}人")print(f"及格率:{pass_count/len(scores)*100:.1f}%")print("="*40)def main():"""主函数"""print("欢迎使用CK学校成绩统计系统")scores = input_scores()print_statistics(scores)# 运行程序main()
三、同级模块间函数调用
在实际开发中,我们经常需要在一个模块中调用另一个模块中定义的函数。Python提供了多种方式来实现跨模块调用。
假设我们有以下项目结构:
CK_School_Project/├── math_tools.py# 数学工具模块├── string_tools.py# 字符串工具模块└── main.py# 主程序
方法1:import 模块名
语法:
import 模块名模块名.函数名(参数)
math_tools.py 文件内容:
# math_tools.py - 数学工具模块PI =3.14159def add(a, b):"""加法"""return a + bdef subtract(a, b):"""减法"""return a - bdef multiply(a, b):"""乘法"""return a * bdef divide(a, b):"""除法"""if b ==0:return"错误:除数不能为零"return a / bdef power(base, exponent):"""幂运算"""return base ** exponent
main.py 文件内容:
# main.py - 主程序import math_tools# 导入整个模块# 使用模块名.函数名的方式调用result1 = math_tools.add(10, 5)result2 = math_tools.subtract(10, 5)result3 = math_tools.multiply(10, 5)result4 = math_tools.divide(10, 5)result5 = math_tools.power(2, 3)print(f"10 + 5 = {result1}")# 10 + 5 = 15print(f"10 - 5 = {result2}")# 10 - 5 = 5print(f"10 * 5 = {result3}")# 10 * 5 = 50print(f"10 / 5 = {result4}")# 10 / 5 = 2.0print(f"2 ^ 3 = {result5}")# 2 ^ 3 = 8# 访问模块中的变量print(f"PI = {math_tools.PI}")# PI = 3.14159
优点: - 代码清晰,明确知道函数来自哪个模块 - 避免命名冲突 - 适合大型项目
缺点: - 每次调用都要写模块名,代码较长
方法2:from 模块名 import 函数名
语法:
from 模块名 import 函数名1, 函数名2, ...函数名(参数)# 直接使用函数名
main.py 文件内容:
# main.py - 主程序from math_tools import add, subtract, multiply# 导入指定函数# 直接使用函数名调用result1 = add(10, 5)result2 = subtract(10, 5)result3 = multiply(10, 5)print(f"10 + 5 = {result1}")# 10 + 5 = 15print(f"10 - 5 = {result2}")# 10 - 5 = 5print(f"10 * 5 = {result3}")# 10 * 5 = 50# divide 和 power 没有导入,无法使用# result4 = divide(10, 5)# NameError: name 'divide' is not defined
优点: - 调用时不需要写模块名,代码简洁 - 只导入需要的函数,节省内存
缺点: - 可能与当前模块的函数名冲突 - 不清楚函数来自哪个模块
方法3:from 模块名 import 函数名 as 别名
语法:
from 模块名 import 函数名 as 别名别名(参数)# 使用别名调用
main.py 文件内容:
# main.py - 主程序from math_tools import add as my_addfrom math_tools import subtract as my_subtractfrom math_tools import multiply as my_multiply# 使用别名调用result1 = my_add(10, 5)result2 = my_subtract(10, 5)result3 = my_multiply(10, 5)print(f"10 + 5 = {result1}")# 10 + 5 = 15print(f"10 - 5 = {result2}")# 10 - 5 = 5print(f"10 * 5 = {result3}")# 10 * 5 = 50# 使用别名可以避免命名冲突def add(a, b):"""自定义的加法函数"""returnf"结果是:{a + b}"print(add(3, 5))# 输出:结果是:8print(my_add(3, 5))# 输出:8
优点: - 解决命名冲突问题 - 可以给函数起更有意义的名字 - 代码简洁
缺点: - 别名过多可能导致混乱
方法4:import 模块名 as 别名
语法:
import 模块名 as 别名别名.函数名(参数)
main.py 文件内容:
# main.py - 主程序import math_tools as mt# 给模块起别名# 使用别名.函数名的方式调用result1 = mt.add(10, 5)result2 = mt.subtract(10, 5)result3 = mt.multiply(10, 5)print(f"10 + 5 = {result1}")# 10 + 5 = 15print(f"10 - 5 = {result2}")# 10 - 5 = 5print(f"10 * 5 = {result3}")# 10 * 5 = 50# 访问模块变量print(f"PI = {mt.PI}")# PI = 3.14159
优点: - 代码简洁 - 避免模块名冲突 - 保持模块的命名空间
缺点: - 需要记住别名
常见应用:在数据科学领域,很多库都有约定俗成的别名:
import numpy as npimport pandas as pdimport matplotlib.pyplot as plt# 使用约定别名data = np.array([1, 2, 3, 4, 5])df = pd.DataFrame(data)plt.plot(data)
方法5:from 模块名 import *
语法:
from 模块名 import*函数名(参数)# 直接使用所有公开的函数和变量
main.py 文件内容:
# main.py - 主程序from math_tools import*# 导入模块中所有内容# 直接使用所有导入的函数和变量result1 = add(10, 5)result2 = subtract(10, 5)result3 = multiply(10, 5)result4 = divide(10, 5)result5 = power(2, 3)print(f"10 + 5 = {result1}")# 10 + 5 = 15print(f"10 - 5 = {result2}")# 10 - 5 = 5print(f"10 * 5 = {result3}")# 10 * 5 = 50print(f"10 / 5 = {result4}")# 10 / 5 = 2.0print(f"2 ^ 3 = {result5}")# 2 ^ 3 = 8print(f"PI = {PI}")# PI = 3.14159
优点: - 使用方便,不需要写模块名
缺点: - 强烈不推荐使用! - 可能导入不需要的内容,浪费内存 - 容易造成命名冲突 - 代码可读性差,不知道函数来自哪里 - 可能覆盖当前模块的同名变量或函数
命名冲突示例:
# 不推荐的做法from math_tools import*def add(a, b):"""当前模块的add函数"""return a + b +100# 此时math_tools中的add已被覆盖result = add(10, 5)print(result)# 输出:115,而不是15
五种方法对比总结
方法 | 语法 | 优点 | 缺点 | 推荐程度 |
方法1 | import 模块名 | 清晰、无冲突 | 代码较长 | ⭐⭐⭐⭐⭐ |
方法2 | from 模块名 import 函数名 | 简洁 | 可能冲突 | ⭐⭐⭐⭐ |
方法3 | from 模块名 import 函数名 as 别名 | 解决冲突 | 别名过多 | ⭐⭐⭐⭐ |
方法4 | import 模块名 as 别名 | 简洁、保持命名空间 | 需记别名 | ⭐⭐⭐⭐⭐ |
方法5 | from 模块名 import * | 方便 | 易冲突、难维护 | ⭐ |
四、下级模块函数调用
在实际项目中,我们通常会将模块组织成包(Package)的形式。包是一个包含__init__.py文件的目录。
1. 项目目录结构
CK_School_Project/├── main.py# 主程序└── utils/# 工具包(目录)├── __init__.py# 包初始化文件├── math_tools.py# 数学工具模块└── string_tools.py# 字符串工具模块
2. 各文件内容
utils/init.py:
# utils/__init__.py# 包初始化文件,可以为空,也可以定义包级别的变量或函数print("utils包已加载")# 可以在这里导入子模块,方便外部使用from .math_tools import add, subtractfrom .string_tools import to_uppercase, to_lowercase
utils/math_tools.py:
# utils/math_tools.pydef add(a, b):"""加法"""return a + bdef subtract(a, b):"""减法"""return a - bdef multiply(a, b):"""乘法"""return a * bdef divide(a, b):"""除法"""if b ==0:return"错误:除数不能为零"return a / b
utils/string_tools.py:
# utils/string_tools.pydef to_uppercase(text):"""转换为大写"""return text.upper()def to_lowercase(text):"""转换为小写"""return text.lower()def reverse_string(text):"""反转字符串"""return text[::-1]def count_words(text):"""统计单词数"""words = text.split()returnlen(words)
main.py:
# main.py - 主程序# 方法1:导入整个包中的模块import utils.math_toolsimport utils.string_toolsresult1 = utils.math_tools.add(10, 5)result2 = utils.string_tools.to_uppercase("hello")print(f"10 + 5 = {result1}")# 10 + 5 = 15print(f"HELLO: {result2}")# HELLO: HELLO# 方法2:使用from导入from utils.math_tools import multiply, dividefrom utils.string_tools import reverse_string, count_wordsresult3 = multiply(4, 5)result4 = divide(20, 4)result5 = reverse_string("CK学校")result6 = count_words("Hello World Python")print(f"4 * 5 = {result3}")# 4 * 5 = 20print(f"20 / 4 = {result4}")# 20 / 4 = 5.0print(f"反转: {result5}")# 反转: 校学KCprint(f"单词数: {result6}")# 单词数: 3# 方法3:如果__init__.py中已经导入,可以直接从包导入from utils import add, to_uppercaseresult7 = add(3, 7)result8 = to_uppercase("ck school")print(f"3 + 7 = {result7}")# 3 + 7 = 10print(f"大写: {result8}")# 大写: CK SCHOOL
3. 相对导入与绝对导入
在包内部的模块之间,可以使用相对导入:
utils/math_tools.py(使用相对导入调用同级模块):
# utils/math_tools.pyfrom .string_tools import to_uppercase# 相对导入def add_and_format(a, b):"""加法并格式化输出"""result = a + breturn to_uppercase(f"结果是{result}")# 测试if__name__=="__main__":print(add_and_format(3, 5))# 结果是8
相对导入语法: - from .module:导入同级模块 - from ..module:导入上级目录的模块 - from ...module:导入上上级目录的模块
4. 完整案例:CK学校学生管理系统
项目结构:
CK_Student_System/├── main.py└── student/├── __init__.py├── info.py# 学生信息模块├── score.py# 成绩管理模块└── report.py# 报表生成模块
student/info.py:
# student/info.py - 学生信息模块def create_student(student_id, name, age, class_name):"""创建学生信息字典"""return {"id": student_id,"name": name,"age": age,"class_name": class_name}def display_student(student):"""显示学生信息"""print(f"学号:{student['id']}")print(f"姓名:{student['name']}")print(f"年龄:{student['age']}")print(f"班级:{student['class_name']}")
student/score.py:
# student/score.py - 成绩管理模块def add_score(student, subject, score):"""添加成绩"""if"scores"notin student:student["scores"] = {}student["scores"][subject] = scoredef calculate_average(student):"""计算平均分"""if"scores"notin student orlen(student["scores"]) ==0:return0total =sum(student["scores"].values())return total /len(student["scores"])def get_grade(average):"""获取等级"""if average >=90:return"A(优秀)"elif average >=80:return"B(良好)"elif average >=70:return"C(中等)"elif average >=60:return"D(及格)"else:return"E(不及格)"
student/report.py:
# student/report.py - 报表生成模块from .score import calculate_average, get_gradedef generate_report(student):"""生成学生成绩报告"""print("\n"+"="*50)print("CK学校学生成绩报告")print("="*50)print(f"学号:{student['id']}")print(f"姓名:{student['name']}")print(f"班级:{student['class_name']}")print("-"*50)if"scores"in student:print("各科成绩:")for subject, score in student["scores"].items():print(f"{subject}:{score}")average = calculate_average(student)grade = get_grade(average)print("-"*50)print(f"平均分:{average:.2f}")print(f"等级:{grade}")else:print("暂无成绩记录")print("="*50)
main.py:
# main.py - 主程序from student.info import create_student, display_studentfrom student.score import add_scorefrom student.report import generate_reportdef main():"""主函数"""print("欢迎使用CK学校学生管理系统")# 创建学生student = create_student("2024001", "张三", 20, "数字经济1班")# 添加成绩add_score(student, "Python程序设计", 92)add_score(student, "数据结构", 85)add_score(student, "数据库原理", 88)add_score(student, "经济学基础", 90)# 生成报告generate_report(student)if__name__=="__main__":main()
运行结果:
欢迎使用CK学校学生管理系统==================================================CK学校学生成绩报告==================================================学号:2024001姓名:张三班级:数字经济1班--------------------------------------------------各科成绩:Python程序设计:92数据结构:85数据库原理:88经济学基础:90--------------------------------------------------平均分:88.75等级:B(良好)==================================================
五、Python内置模块的调用
除了自定义模块,Python还提供了丰富的内置模块(标准库),我们可以直接导入使用。
知识回顾:在第1章1.3.2节,我们学习了Python程序的模块及引用。
1. math模块
import math# 常用函数print(math.sqrt(16))# 平方根:4.0print(math.pow(2, 3))# 幂运算:8.0print(math.floor(3.7))# 向下取整:3print(math.ceil(3.2))# 向上取整:4print(math.fabs(-5))# 绝对值:5.0# 常量print(math.pi)# 圆周率:3.141592653589793print(math.e)# 自然常数:2.718281828459045
2. random模块
知识回顾:在第4章4.3.3节,我们学习了random库的使用。
import random# 生成随机数print(random.random())# 0到1之间的随机浮点数print(random.randint(1, 100))# 1到100之间的随机整数print(random.uniform(1.5, 5.5))# 1.5到5.5之间的随机浮点数# 从序列中随机选择colors = ["红", "绿", "蓝", "黄"]print(random.choice(colors))# 随机选择一个元素# 打乱序列numbers = [1, 2, 3, 4, 5]random.shuffle(numbers)print(numbers)# 随机打乱后的列表
3. time模块
知识预告:time库将在6.5.1节详细讲解。
import time# 获取当前时间戳print(time.time())# 格式化时间print(time.strftime("%Y-%m-%d %H:%M:%S"))# 程序暂停print("开始")time.sleep(2)# 暂停2秒print("结束")
4. os模块
import os# 获取当前工作目录print(os.getcwd())# 列出目录内容print(os.listdir("."))# 创建目录# os.mkdir("new_folder")# 检查文件是否存在print(os.path.exists("main.py"))

6.1.4 AI辅助学习:用AI加深对本节知识的理解
一、为什么要用AI辅助学习
在当今数字化时代,AI已经成为学习编程的重要辅助工具。通过与AI对话,你可以:
1.即时获得解答:遇到问题时,可以立即获得详细的解释
2.个性化学习:AI可以根据你的水平调整讲解的深度
3.代码生成与优化:AI可以帮助你生成代码示例,并给出优化建议
4.拓展思维:AI可以提供多种解决方案,帮助你拓展编程思维
二、如何有效地与AI对话
1. 提问的基本原则
·明确具体:清楚地描述你的问题或需求
·提供上下文:说明你的学习背景和当前水平
·循序渐进:从简单问题开始,逐步深入
·验证思考:不要盲目接受AI的答案,要思考验证
2. 提示词模板
以下是一些实用的提示词模板,你可以直接使用或根据需要修改:
三、函数基础练习——AI提示词设计
练习1:理解函数定义
提示词:
我是一名Python初学者,正在学习函数的定义。请帮我生成一个函数,功能是计算一个正整数的阶乘。要求:1. 函数名为 factorial2. 参数为 n(正整数)3. 返回 n 的阶乘4. 包含详细的注释说明5. 给出调用示例和预期输出
预期AI回复示例:
def factorial(n):"""计算正整数n的阶乘参数:n (int): 正整数返回:int: n的阶乘,即 n! = n * (n-1) * ... * 2 * 1示例:>>> factorial(5)120"""result =1for i inrange(1, n +1):result *= ireturn result# 调用示例print(factorial(5))# 输出:120print(factorial(10))# 输出:3628800
练习2:输出爱心图案
提示词:
请帮我编写一个Python函数,在控制台输出一个爱心图案。要求:1. 函数名为 print_heart2. 可以通过参数控制爱心的大小3. 使用字符 '*' 或 '♥' 来绘制4. 添加详细注释说明代码逻辑
预期AI回复示例:
def print_heart(size=1):"""在控制台输出爱心图案参数:size (float): 爱心大小的缩放比例,默认为1爱心数学方程:(x² + y² - 1)³ - x²y³ = 0"""# 根据size调整图案大小scale =int(6* size)for y inrange(scale, -scale -1, -1):line =""for x inrange(-2* scale, 2* scale +1):# 爱心方程if ((x *0.05) **2+ (y *0.1) **2-1) **3- (x *0.05) **2* (y *0.1) **3<=0:line +="♥"else:line +=" "print(line)# 调用示例print("默认大小爱心:")print_heart()print("\n更大的爱心:")print_heart(1.5)
输出效果:
默认大小爱心:♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥ ♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥ ♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥ ♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
练习3:输出三角形图案
提示词:
请帮我编写一个Python函数,输出各种三角形图案。要求:1. 函数名为 print_triangle2. 参数包括:行数(rows)、字符(char)、方向(direction: 'up'/'down'/'left'/'right')3. 根据方向参数输出不同方向的三角形4. 给出多个调用示例
预期AI回复示例:
def print_triangle(rows, char='*', direction='up'):"""输出各种方向的三角形图案参数:rows (int): 三角形的行数char (str): 用于绘制三角形的字符,默认为 '*'direction (str): 三角形方向- 'up': 向上的三角形- 'down': 向下的三角形- 'left': 向左的三角形- 'right': 向右的三角形"""if direction =='up':for i inrange(1, rows +1):spaces =' '* (rows - i)stars = char * (2* i -1)print(spaces + stars)elif direction =='down':for i inrange(rows, 0, -1):spaces =' '* (rows - i)stars = char * (2* i -1)print(spaces + stars)elif direction =='left':for i inrange(1, rows +1):print(char * i)for i inrange(rows -1, 0, -1):print(char * i)elif direction =='right':for i inrange(1, rows +1):spaces =' '* (rows - i)print(spaces + char * i)for i inrange(rows -1, 0, -1):spaces =' '* (rows - i)print(spaces + char * i)# 调用示例print("向上的三角形:")print_triangle(5, '*', 'up')print("\n向下的三角形:")print_triangle(5, '#', 'down')print("\n向左的三角形:")print_triangle(4, '@', 'left')print("\n向右的三角形:")print_triangle(4, '+', 'right')
输出效果:
向上的三角形:********* ****************向下的三角形:######### ################向左的三角形:@@@@@@@@@@@@@@@@向右的三角形:+++ +++++++ ++++++
练习4:输出菱形图案
提示词:
请帮我编写一个Python函数,输出菱形图案。要求:1. 函数名为 print_diamond2. 参数为菱形的半高(即最宽处的行数)3. 可以自定义填充字符4. 给出调用示例
预期AI回复示例:
def print_diamond(half_height, char='*'):"""输出菱形图案参数:half_height (int): 菱形的半高(从顶点到中间的行数)char (str): 用于绘制菱形的字符"""# 上半部分(包括中间行)for i inrange(1, half_height +1):spaces =' '* (half_height - i)chars = char * (2* i -1)print(spaces + chars)# 下半部分for i inrange(half_height -1, 0, -1):spaces =' '* (half_height - i)chars = char * (2* i -1)print(spaces + chars)# 调用示例print("小菱形:")print_diamond(3)print("\n大菱形:")print_diamond(5, '♦')print("\nCK学校专属菱形:")print_diamond(4, '★')
练习5:输出数字金字塔
提示词:
请帮我编写一个Python函数,输出数字金字塔。要求:1. 函数名为 print_number_pyramid2. 参数为金字塔的层数3. 每层显示对应的数字,如第1层显示1,第2层显示2...4. 给出调用示例
预期AI回复示例:
def print_number_pyramid(layers):"""输出数字金字塔参数:layers (int): 金字塔的层数示例(layers=4):1222333334444444"""for i inrange(1, layers +1):# 计算空格数spaces =' '* (layers - i)# 计算数字个数(第i层有2i-1个数字)numbers =str(i) * (2* i -1)print(spaces + numbers)# 调用示例print("4层数字金字塔:")print_number_pyramid(4)print("\n6层数字金字塔:")print_number_pyramid(6)
输出效果:
4层数字金字塔:1222 3333344444446层数字金字塔:1222333334444444 55555555566666666666
练习6:输出乘法口诀表
提示词:
请帮我编写一个Python函数,输出九九乘法口诀表。要求:1. 函数名为 print_multiplication_table2. 可以指定输出的行数(默认为9)3. 输出格式整齐美观4. 给出调用示例
预期AI回复示例:
def print_multiplication_table(rows=9):"""输出乘法口诀表参数:rows (int): 输出的行数,默认为9输出格式:1×1=11×2=22×2=41×3=32×3=63×3=9..."""for i inrange(1, rows +1):line =""for j inrange(1, i +1):# 使用格式化字符串保证对齐line +=f"{j}×{i}={i*j:<2}"print(line)# 调用示例print("完整九九乘法表:")print_multiplication_table()print("\n前5行乘法表:")print_multiplication_table(5)
输出效果:
完整九九乘法表:1×1=11×2=22×2=41×3=32×3=63×3=91×4=42×4=83×4=124×4=161×5=52×5=103×5=154×5=205×5=251×6=62×6=123×6=184×6=245×6=306×6=361×7=72×7=143×7=214×7=285×7=356×7=427×7=491×8=82×8=163×8=244×8=325×8=406×8=487×8=568×8=641×9=92×9=183×9=274×9=365×9=456×9=547×9=638×9=729×9=81
练习7:输出简单的ASCII艺术
提示词:
请帮我编写一个Python函数,输出CK学校的ASCII艺术标志。要求:1. 函数名为 print_ck_logo2. 使用字符绘制"CK"字样3. 可以调整大小4. 给出调用示例
预期AI回复示例:
def print_ck_logo(size=1):"""输出CK学校ASCII艺术标志参数:size (int): 大小缩放比例"""# 基础CK标志ck_art = ["██████╗██╗██╗███████╗", " ██╔════╝██║██║██╔════╝", " ██║███████║█████╗", " ██║██╔══██║██╔══╝", " ╚██████╗██║██║███████╗", "╚═════╝╚═╝╚═╝╚══════╝"]print("\n"+"="*30)print("CK School Logo")print("="*30)for line in ck_art:# 根据size重复输出for _ inrange(size):print(line)print("="*30)# 调用示例print_ck_logo()print("\n简版CK标志:")print("""____ _/ ___| | __ | || |/ / | |___|< \\____|_|\\_\\""")
练习8:动态进度条
提示词:
请帮我编写一个Python函数,模拟进度条效果。要求:1. 函数名为 show_progress2. 参数为总任务数3. 使用time模块模拟任务执行4. 显示百分比和进度条
预期AI回复示例:
import timedef show_progress(total_tasks, task_name="处理中"):"""显示进度条参数:total_tasks (int): 总任务数task_name (str): 任务名称"""for i inrange(total_tasks +1):# 计算百分比percent = i / total_tasks *100# 计算进度条长度bar_length =30filled =int(bar_length * i / total_tasks)bar ='█'* filled +'░'* (bar_length - filled)# 打印进度(\r使光标回到行首)print(f"\r{task_name}: [{bar}] {percent:.1f}%", end="")# 模拟任务执行time.sleep(0.1)print()# 换行# 调用示例print("开始执行任务...")show_progress(50, "数据处理")print("任务完成!")print("\n另一个任务:")show_progress(30, "文件下载")
输出效果(动态显示):
开始执行任务...数据处理: [██████████████████████████████] 100.0%任务完成!另一个任务:文件下载: [██████████████████████████████] 100.0%
四、综合练习——CK学校成绩分析系统
提示词:
请帮我编写一个完整的Python程序,实现CK学校成绩分析系统。要求:1. 使用模块化设计,将不同功能封装成函数2. 包含以下功能:- 录入学生成绩- 计算平均分、最高分、最低分- 统计各分数段人数- 输出成绩报告3. 使用前面学过的函数定义和调用知识4. 添加详细注释
预期AI回复示例:
"""CK学校成绩分析系统演示函数的定义与调用"""def input_scores():"""录入学生成绩返回:list: 成绩列表"""scores = []print("请输入学生成绩(输入-1结束):")whileTrue:try:score =float(input("成绩:"))if score ==-1:breakif0<= score <=100:scores.append(score)else:print("成绩应在0-100之间,请重新输入。")exceptValueError:print("输入无效,请输入数字。")return scoresdef calculate_average(scores):"""计算平均分参数:scores (list): 成绩列表返回:float: 平均分"""iflen(scores) ==0:return0returnsum(scores) /len(scores)def find_max_min(scores):"""找出最高分和最低分参数:scores (list): 成绩列表返回:tuple: (最高分, 最低分)"""iflen(scores) ==0:return (0, 0)return (max(scores), min(scores))def count_grade_distribution(scores):"""统计各分数段人数参数:scores (list): 成绩列表返回:dict: 各分数段人数统计"""distribution = {"优秀(90-100)": 0, "良好(80-89)": 0, "中等(70-79)": 0, "及格(60-69)": 0, "不及格(0-59)": 0}for score in scores:if score >=90:distribution["优秀(90-100)"] +=1elif score >=80:distribution["良好(80-89)"] +=1elif score >=70:distribution["中等(70-79)"] +=1elif score >=60:distribution["及格(60-69)"] +=1else:distribution["不及格(0-59)"] +=1return distributiondef generate_report(scores):"""生成成绩分析报告参数:scores (list): 成绩列表"""print("\n"+"="*50)print("CK学校成绩分析报告")print("="*50)iflen(scores) ==0:print("暂无成绩数据!")return# 基本信息print(f"学生人数:{len(scores)}人")# 平均分average = calculate_average(scores)print(f"平均分:{average:.2f}分")# 最高分和最低分max_score, min_score = find_max_min(scores)print(f"最高分:{max_score}分")print(f"最低分:{min_score}分")# 分数段分布print("-"*50)print("分数段分布:")distribution = count_grade_distribution(scores)for grade, count in distribution.items():percentage = count /len(scores) *100bar ="█"*int(percentage /5)# 每5%一个方块print(f"{grade}:{count}人 ({percentage:.1f}%) {bar}")print("="*50)def main():"""主函数"""print("="*50)print("欢迎使用CK学校成绩分析系统")print("="*50)# 录入成绩scores = input_scores()# 生成报告generate_report(scores)# 运行程序if__name__=="__main__":main()
五、AI辅助学习建议
1. 学习流程建议
1. 先自己思考 → 2. 尝试编写代码 → 3. 遇到问题问AI → 4. 理解AI的解答 → 5. 自己重写代码
2. 有效提问技巧
技巧 | 示例 |
说明背景 | “我是Python初学者,正在学习函数…” |
明确需求 | “请帮我编写一个计算阶乘的函数” |
指定要求 | “要求使用for循环,不要使用递归” |
请求解释 | “请解释每一行代码的作用” |
追问细节 | “为什么这里要用return而不是print?” |
3. 避免过度依赖AI
·先思考再提问:不要一遇到问题就问AI
·理解而非复制:确保理解AI给出的代码
·举一反三:学会将AI的解答应用到类似问题
·验证答案:运行代码验证AI的答案是否正确
六、课后练习
请使用AI辅助完成以下练习:
练习1:温度转换函数
提示词模板:
请帮我编写一个温度转换函数,要求:1. 函数名为 convert_temperature2. 参数为温度值和转换类型('C2F'摄氏转华氏,'F2C'华氏转摄氏)3. 返回转换后的温度值4. 包含参数验证5. 给出调用示例
练习2:简单计算器
提示词模板:
请帮我编写一个简单计算器程序,要求:1. 使用函数实现加减乘除四种运算2. 主函数提供菜单选择3. 可以循环计算直到用户选择退出4. 处理除数为零的情况
练习3:猜数字游戏
提示词模板:
请帮我编写一个猜数字游戏,要求:1. 使用random模块生成1-100的随机数2. 用户输入猜测,程序提示"大了"或"小了"3. 记录猜测次数4. 使用函数封装游戏逻辑5. 可以多次游戏

本节小结
知识点总结
知识点 | 核心内容 |
模块化设计 | 将复杂问题分解为独立模块,提高代码可读性和可维护性 |
函数定义 | 使用def关键字定义函数,包括函数名、参数列表、函数体、返回值 |
函数名 | 遵循标识符命名规则,建议使用snake_case命名法 |
形式参数 | 函数定义时的变量名,用于接收调用时传入的数据 |
冒号 | 标识代码块的开始,不能省略 |
return语句 | 结束函数执行并返回值,无return则返回None |
函数调用 | 函数必须先定义后调用,参数数量和类型要匹配 |
模块间调用 | 使用import语句导入模块,有多种导入方式 |
重点难点
1.重点:函数的定义格式、参数传递、返回值
2.难点:模块间函数调用的多种方式、形参与实参的区别