# ==================== Python 函数全面教学课程 ====================
"""
本课程从零基础开始,全面讲解 Python 函数的各个方面,包括:
1. 函数的基本概念与定义方式(函数的基本定义)
2. 函数参数的多种类型(必选、默认、可变、关键字等)
3. 函数的返回值类型(基本类型、容器、函数、生成器等)
4. 函数作用域与变量生命周期
5. 函数的高级特性(闭包、递归、装饰器、高阶函数)
6. 函数在实际开发中的综合应用
每个知识点都配有详细注释和示例代码,帮助你逐步掌握函数编程的核心思想。
"""
# ==================== 1. 函数基础概念 ====================
"""
📚 什么是函数?
函数是一段可重复使用的代码块,它接受输入(参数),执行特定任务,并返回结果。
函数就像厨房里的食谱:输入食材 → 按照步骤加工 → 输出菜肴
🔍 为什么使用函数?
1. 代码复用:避免重复编写相同代码
2. 模块化:将复杂问题分解为简单部分
3. 抽象封装:隐藏实现细节,提供简单接口
4. 提高可读性:通过函数名表达意图
5. 易于维护:修改只需在一处进行
"""
# 示例1:简单函数定义与调用
def welcome_message(name: str) -> str: # 定义函数,参数为字符串,返回字符串
"""欢迎消息函数(返回字符串)""" # 函数文档字符串
message = f"您好,{name}!欢迎使用Python函数教学" # 创建欢迎消息
return message # 返回结果
# 调用函数并打印结果
print("\n=== 函数基础示例 ===") # 打印示例标题
result = welcome_message("张三") # 调用函数并存储结果
print(result) # 打印结果:您好,张三!欢迎使用Python函数教学
# 示例2:函数复用价值(计算圆面积)
def calculate_area(radius: float) -> float: # 定义函数,参数为浮点数,返回浮点数
"""计算圆面积(返回浮点数)""" # 函数文档字符串
pi = 3.14 # 定义圆周率近似值
area = pi * (radius ** 2) # 计算圆面积
return area # 返回计算结果
# 复用计算函数
radius1 = 3 # 定义第一个半径
area1 = calculate_area(radius1) # 计算第一个圆面积
print(f"\n半径{radius1}的圆面积: {area1:.2f}") # 打印结果(保留两位小数)
radius2 = 5 # 定义第二个半径
area2 = calculate_area(radius2) # 计算第二个圆面积
print(f"半径{radius2}的圆面积: {area2:.2f}") # 打印结果(保留两位小数)
# 示例3:函数作为模块化工具(BMI计算)
def calculate_bmi(weight_kg: float, height_m: float) -> tuple: # 定义函数,返回元组
"""计算BMI并返回结果和分类(返回元组)""" # 函数文档字符串
bmi = weight_kg / (height_m ** 2) # 计算BMI值
# 根据BMI值确定分类
if bmi < 18.5: # BMI小于18.5为偏瘦
category = "偏瘦"
elif bmi < 24: # BMI在18.5-24之间为正常
category = "正常"
else: # BMI大于等于24为超重
category = "超重"
return bmi, category # 返回包含两个值的元组
# 使用示例
print("\nBMI计算示例:") # 打印示例标题
bmi_result, status_result = calculate_bmi(70, 1.75) # 调用函数并解包结果
print(f"BMI值: {bmi_result:.1f}") # 打印BMI值(保留一位小数)
print(f"健康状态: {status_result}") # 打印健康状态
# ==================== 2. 函数定义与使用 ====================
"""
📚 函数定义的基本结构:
def 函数名(参数1: 类型, 参数2: 类型 = 默认值) -> 返回类型:
'''函数文档字符串'''
# 函数体
return 结果
🔍 为什么有多种参数类型?
1. 提高灵活性:适应不同调用场景
2. 简化调用:默认参数减少必要输入
3. 处理不确定输入:*args和**kwargs处理可变参数
4. 强制关键字参数:提高代码可读性和安全性
"""
# 1. 无返回值函数
def greet(name: str) -> None: # 定义无返回值函数
"""向用户打招呼(无返回值)""" # 函数文档字符串
print(f"Hello, {name}!") # 直接打印问候语
print("\n=== 无返回值函数示例 ===") # 打印示例标题
greet("Alice") # 调用函数
# 2. 带返回值的函数
def add(a: int, b: int) -> int: # 定义带返回值的函数
"""返回两个数的和(返回整数)""" # 函数文档字符串
return a + b # 返回计算结果
print("\n=== 带返回值函数示例 ===") # 打印示例标题
result = add(3, 5) # 调用函数并存储结果
print(f"3 + 5 = {result}") # 打印结果
# 3. 多种参数类型详解
def complex_func(a: int, b: int = 2, *args, **kwargs) -> tuple: # 定义支持多种参数类型的函数
"""参数类型演示函数(返回元组)""" # 函数文档字符串
print("\n=== 参数分析开始 ===") # 打印参数分析开始标记
print(f"必选参数a: {a} (类型: {type(a).__name__})") # 打印必选参数信息
print(f"默认参数b: {b} (类型: {type(b).__name__})") # 打印默认参数信息
# 处理可变位置参数
if args: # 检查是否有可变位置参数
print("\n可变位置参数(args):") # 打印标题
for i, arg in enumerate(args): # 遍历所有可变位置参数
print(f" args[{i}] = {arg} (类型: {type(arg).__name__})") # 打印参数信息
# 处理可变关键字参数
if kwargs: # 检查是否有可变关键字参数
print("\n可变关键字参数(kwargs):") # 打印标题
for key, value in kwargs.items(): # 遍历所有可变关键字参数
print(f" {key} = {value} (类型: {type(value).__name__})") # 打印参数信息
print("=== 参数分析结束 ===") # 打印参数分析结束标记
return a + b, a * b # 返回计算结果元组
print("\n=== 多种参数类型示例 ===") # 打印示例标题
print("调用1: 只传必选参数") # 打印调用说明
sum_result, product_result = complex_func(5) # 调用函数(只传必选参数)
print(f"和: {sum_result}, 积: {product_result}") # 打印结果
print("\n调用2: 传所有类型参数") # 打印调用说明
result_tuple = complex_func(3, 4, 5, 6, name="Bob", age=25) # 调用函数(传所有类型参数)
print(f"返回结果: {result_tuple}") # 打印结果
# 4. 仅关键字参数函数
def create_user(*, username: str, email: str, is_admin: bool = False) -> dict: # 定义仅关键字参数函数
"""创建用户账户(返回字典)""" # 函数文档字符串
return { # 返回用户信息字典
"username": username, # 用户名
"email": email, # 邮箱
"is_admin": is_admin # 管理员状态
}
print("\n=== 仅关键字参数示例 ===") # 打印示例标题
user = create_user(username="tech_guru", email="guru@example.com") # 调用函数(使用关键字参数)
print(f"创建的用户: {user}") # 打印结果
# ==================== 3. 函数作用域与特性 ====================
"""
📚 作用域概念:
作用域决定了变量的可见性和生命周期,Python有四种作用域:
1. 局部作用域(Local) - 函数内部
2. 闭包函数作用域(Enclosing) - 嵌套函数中
3. 全局作用域(Global) - 模块级别
4. 内置作用域(Built-in) - Python内置名称
🔍 为什么理解作用域重要?
1. 避免变量冲突:不同作用域的同名变量互不影响
2. 管理变量生命周期:局部变量在函数结束后销毁
3. 实现闭包:通过作用域链保存状态
4. 控制访问权限:限制变量的可见范围
"""
# 1. 作用域示例
global_var = "我是全局变量" # 定义全局变量
def scope_test() -> int: # 定义作用域测试函数
"""作用域测试函数(返回整数)""" # 函数文档字符串
local_var = "我是局部变量" # 定义局部变量
print(f"\n函数内访问全局变量: {global_var}") # 访问全局变量
global another_global # 声明要修改全局变量
another_global = "我在函数中定义的全局变量" # 定义新的全局变量
square = lambda x: x ** 2 # 定义lambda表达式(匿名函数)
return square(5) # 返回计算结果
print("\n=== 作用域示例 ===") # 打印示例标题
print(f"5的平方: {scope_test()}") # 调用函数并打印结果
print(f"新全局变量: {another_global}") # 访问新全局变量
# 2. 闭包详解
"""
📚 什么是闭包?
闭包是一个函数对象,它可以"记住"并访问创建它的词法作用域中的变量,
即使外部函数已经执行完毕。
闭包三要素:
1. 外部函数:定义闭包的环境
2. 内部函数:访问外部函数变量的函数
3. 捕获的变量:内部函数访问的外部变量
🔍 为什么使用闭包?
1. 状态保持:在函数调用之间保持状态
2. 数据封装:创建私有变量
3. 函数工厂:生成具有不同配置的函数
4. 回调函数:在事件处理中保持上下文
"""
def counter_factory(initial: int = 0) -> callable: # 定义闭包工厂函数
"""创建计数器闭包(返回函数)""" # 函数文档字符串
count = initial # 闭包内部状态(捕获的变量)
def increment() -> int: # 定义内部函数(闭包)
"""内部计数器函数(返回整数)""" # 函数文档字符串
nonlocal count # 声明count来自外部作用域(非全局)
count += 1 # 修改闭包状态
return count # 返回当前计数值
return increment # 返回内部函数(闭包)
print("\n=== 闭包示例 ===") # 打印示例标题
print("创建初始值为10的计数器") # 打印说明
counter1 = counter_factory(10) # 创建计数器闭包(初始值10)
print("第一次调用:", counter1()) # 第一次调用(输出11)
print("第二次调用:", counter1()) # 第二次调用(输出12)
print("\n创建初始值为0的计数器") # 打印说明
counter2 = counter_factory() # 创建计数器闭包(初始值0)
print("第一次调用:", counter2()) # 第一次调用(输出1)
print("第二次调用:", counter2()) # 第二次调用(输出2)
# 3. 递归函数
"""
📚 什么是递归?
递归是函数直接或间接调用自身的过程。
🔍 为什么使用递归?
1. 解决分而治之问题:如树遍历、分治算法
2. 简化代码:对某些问题比循环更简洁
3. 数学计算:自然适合数学递归定义(如阶乘、斐波那契数列)
❗ 注意事项:
1. 必须有基本情况(终止条件)
2. 递归深度有限制(可通过sys.setrecursionlimit调整)
3. 可能效率较低(重复计算)
"""
def factorial(n: int) -> int: # 定义递归函数
"""计算阶乘的递归函数(返回整数)""" # 函数文档字符串
if n == 0: # 基本情况(终止条件)
return 1 # 0的阶乘是1
return n * factorial(n - 1) # 递归调用
print("\n=== 递归函数示例 ===") # 打印示例标题
print(f"0! = {factorial(0)}") # 计算0的阶乘
print(f"1! = {factorial(1)}") # 计算1的阶乘
print(f"5! = {factorial(5)}") # 计算5的阶乘
# ==================== 4. 函数返回类型详解 ====================
"""
📚 Python函数可以返回多种类型:
1. 基本类型:int, float, str, bool
2. 容器类型:list, tuple, dict, set
3. 函数类型:闭包函数
4. 生成器:使用yield关键字
5. None:无返回值
🔍 为什么需要多种返回类型?
1. 灵活性:适应不同场景需求
2. 高效处理大数据:生成器节省内存
3. 创建工厂函数:返回定制化函数
4. 结构化数据:返回容器类型组织多个值
"""
# 1. 返回列表
def get_even_numbers(n: int) -> list: # 定义返回列表的函数
"""获取前n个偶数(返回列表)""" # 函数文档字符串
return [2 * i for i in range(1, n + 1)] # 使用列表推导式生成偶数列表
print("\n=== 返回列表示例 ===") # 打印示例标题
print("前5个偶数:", get_even_numbers(5)) # 调用函数并打印结果
# 2. 返回字典
def create_person(name: str, age: int) -> dict: # 定义返回字典的函数
"""创建人员信息字典(返回字典)""" # 函数文档字符串
return { # 返回人员信息字典
"name": name, # 姓名
"age": age, # 年龄
"adult": age >= 18 # 是否成年(布尔值)
}
print("\n=== 返回字典示例 ===") # 打印示例标题
person = create_person("王五", 30) # 调用函数
print(f"人员信息: 姓名={person['name']}, 年龄={person['age']}, 成年={person['adult']}") # 打印结果
# 3. 返回函数
def multiplier_factory(factor: int) -> callable: # 定义返回函数的函数
"""创建乘法器函数(返回函数)""" # 函数文档字符串
def multiply(x: int) -> int: # 定义内部函数
"""实际执行乘法的函数""" # 函数文档字符串
return x * factor # 返回乘法结果
return multiply # 返回内部函数
print("\n=== 返回函数示例 ===") # 打印示例标题
double = multiplier_factory(2) # 创建乘以2的函数
triple = multiplier_factory(3) # 创建乘以3的函数
print(f"5的双倍: {double(5)}") # 调用函数并打印结果
print(f"5的三倍: {triple(5)}") # 调用函数并打印结果
# 4. 返回生成器
def fibonacci(n: int): # 定义返回生成器的函数
"""生成斐波那契数列(返回生成器)""" # 函数文档字符串
a, b = 0, 1 # 初始化斐波那契数列前两个值
for _ in range(n): # 循环n次
yield a # 生成当前值
a, b = b, a + b # 更新下一个值
print("\n=== 返回生成器示例 ===") # 打印示例标题
print("斐波那契数列(前10个):") # 打印标题
for num in fibonacci(10): # 遍历生成器
print(num, end=" ") # 打印数值(用空格分隔)
# ==================== 5. 函数进阶特性 ====================
"""
📚 高阶函数:
高阶函数是接受其他函数作为参数或返回函数作为结果的函数。
🔍 为什么使用高阶函数?
1. 抽象通用模式:如map、filter、reduce
2. 实现策略模式:运行时改变行为
3. 创建函数组合:将简单函数组合成复杂操作
"""
# 1. 高阶函数示例
def apply_operation(func: callable, data: list) -> list: # 定义高阶函数
"""将函数应用到列表每个元素(返回列表)""" # 函数文档字符串
return [func(item) for item in data] # 使用列表推导式应用函数
print("\n\n=== 高阶函数示例 ===") # 打印示例标题
numbers = [1, 2, 3, 4] # 定义数字列表
squared = apply_operation(lambda x: x ** 2, numbers) # 应用平方函数
print("数字平方:", squared) # 打印结果
"""
📚 装饰器:
装饰器是一种特殊的高阶函数,它接受一个函数并返回一个新函数,
用于在不修改原函数代码的情况下增强其功能。
🔍 为什么使用装饰器?
1. 代码复用:避免重复相同逻辑(如日志、计时)
2. 分离关注点:保持核心逻辑纯净
3. 动态添加功能:运行时增强函数
4. 可组合性:多个装饰器可叠加使用
"""
# 2. 装饰器示例
def timing_decorator(func: callable) -> callable: # 定义装饰器函数
"""测量函数执行时间的装饰器(返回函数)""" # 函数文档字符串
def wrapper(*args, **kwargs): # 定义包装函数
import time # 导入时间模块
start = time.time() # 记录开始时间
result = func(*args, **kwargs) # 调用原始函数
end = time.time() # 记录结束时间
print(f"{func.__name__} 执行耗时: {end - start:.6f}秒") # 打印执行时间
return result # 返回原始函数结果
return wrapper # 返回包装函数
@timing_decorator # 应用装饰器
def calculate_sum(n: int) -> int: # 定义被装饰的函数
"""计算1到n的和(返回整数)""" # 函数文档字符串
return sum(range(1, n + 1)) # 计算1到n的和
print("\n=== 装饰器示例 ===") # 打印示例标题
print(f"1到1000000的和: {calculate_sum(1000000)}") # 调用函数并打印结果
# 3. 函数文档和注解
def format_user_info(name: str, age: int, email: str = "") -> str: # 定义带文档和注解的函数
"""
格式化用户信息(返回字符串)
为什么使用函数文档和注解?
1. 提高可读性:明确函数目的和使用方式
2. IDE支持:提供自动提示和类型检查
3. 文档生成:自动生成API文档
4. 类型提示:减少运行时错误
参数:
name: 用户名
age: 用户年龄
email: 用户邮箱(可选)
返回:
格式化后的用户信息字符串
"""
info = f"姓名: {name}, 年龄: {age}" # 基础信息
if email: # 如果有邮箱
info += f", 邮箱: {email}" # 添加邮箱信息
return info # 返回完整信息
print("\n=== 函数文档和注解示例 ===") # 打印示例标题
print(format_user_info("李四", 28, "lisi@example.com")) # 调用函数并打印结果
print("函数注解:", format_user_info.__annotations__) # 打印函数注解
print("函数文档:", format_user_info.__doc__) # 打印函数文档字符串
# ==================== 6. 综合应用 ====================
"""
📚 综合应用场景:
将前面学到的函数知识应用于实际开发场景
"""
# 1. 电商折扣计算
def calculate_discount(price: float,
user_type: str = "regular",
*coupons: float) -> float: # 定义电商折扣计算函数
"""
计算商品最终价格(返回浮点数)
应用技术:
- 默认参数
- 可变参数
- 字典映射
- 条件判断
参数:
price: 商品原价
user_type: 用户类型 (regular/vip/premium)
*coupons: 优惠券折扣列表
返回:
商品最终价格
"""
# 用户折扣映射
discounts = {
"regular": 0.0, # 普通用户无折扣
"vip": 0.1, # VIP用户9折
"premium": 0.2 # 高级用户8折
}
# 计算最大优惠券折扣
coupon_discount = max(coupons) if coupons else 0 # 取最大优惠券折扣
# 应用最高折扣(用户折扣和优惠券取最大)
discount_rate = max(discounts.get(user_type, 0), coupon_discount)
# 计算折扣后价格
discounted_price = price * (1 - discount_rate)
# 确保不低于成本价(7折)
min_price = price * 0.7
return max(discounted_price, min_price) # 返回最终价格
print("\n=== 电商折扣计算 ===") # 打印示例标题
print("VIP用户购买1000元商品:", calculate_discount(1000, 'vip')) # VIP用户无优惠券
print("高级用户使用15%优惠券:", calculate_discount(1000, 'premium', 0.15)) # 高级用户有优惠券
print("普通用户使用25%优惠券:", calculate_discount(1000, 'regular', 0.25)) # 普通用户有优惠券
# 2. 分页生成器
def paginate(data: list, page_size: int): # 定义分页生成器函数
"""
分页生成器(返回生成器)
应用技术:
- 生成器函数
- 切片操作
- 枚举函数
参数:
data: 数据集
page_size: 每页大小
生成:
每页的数据切片
"""
for i in range(0, len(data), page_size): # 按页大小循环
yield data[i:i + page_size] # 生成当前页数据
print("\n=== 分页生成器 ===") # 打印示例标题
big_data = list(range(1, 101)) # 创建1-100的数据集
print("分页显示(每页10条):") # 打印标题
for page_number, page in enumerate(paginate(big_data, 10), 1): # 遍历分页结果
print(f"第{page_number}页: {page[:5]}...") # 只显示前5项防止过长
# 3. 数据分析管道
def data_analysis_pipeline(data: list): # 定义数据分析管道函数
"""
数据分析管道(返回生成器)
应用技术:
- 数据过滤
- 异常处理
- 生成器
- 数据标准化
步骤:
1. 过滤有效数字
2. 归一化处理(0-1范围)
"""
# 过滤有效数据
valid_data = [x for x in data if isinstance(x, (int, float))] # 只保留数字类型
# 如果没有有效数据,直接返回
if not valid_data: # 检查有效数据是否为空
return # 提前返回
# 计算最小值和最大值
min_val = min(valid_data) # 最小值
max_val = max(valid_data) # 最大值
# 避免除以零错误
if min_val == max_val: # 所有值相同的情况
for x in valid_data: # 遍历有效数据
yield 0.0 # 归一化为0
else:
for x in valid_data: # 遍历有效数据
yield (x - min_val) / (max_val - min_val) # 计算归一化值
print("\n=== 数据分析管道 ===") # 打印示例标题
mixed_data = [10, 15, 'a', 20, 25, None, 30, 35] # 测试数据(包含非数字值)
print("数据标准化结果:") # 打印标题
for value in data_analysis_pipeline(mixed_data): # 遍历标准化结果
print(f"{value:.2f}", end=" ") # 打印格式化结果(保留两位小数)
print("\n\n=== 课程结束 ===") # 课程结束标记
优化下,得按照大纲的顺序来讲啊1. 函数的基本概念与定义方式(函数的基本定义)
2. 函数参数的多种类型(必选、默认、可变、关键字等)
3. 函数的返回值类型(基本类型、容器、函数、生成器等)
4. 函数作用域与变量生命周期
5. 函数的高级特性(闭包、递归、装饰器、高阶函数)
6. 函数在实际开发中的综合应用,现在感觉乱七八糟的
最新发布