07-Python函数进阶
Python函数进阶全面总结
一、函数多返回值
1.1 多返回值概念
在Python中,函数可以返回多个值,这些值会以元组的形式返回。
def multi_return():
return 1, 2, 3 # 返回多个值
result = multi_return()
print(result) # 输出:(1, 2, 3)
print(type(result)) # 输出:<class 'tuple'>
1.2 多返回值解包
可以直接用多个变量接收返回值,Python会自动解包:
def get_student_info():
name = "张三"
age = 18
score = 95.5
return name, age, score # 返回三个值
# 使用多个变量接收返回值
student_name, student_age, student_score = get_student_info()
print(f"姓名:{student_name},年龄:{student_age},成绩:{student_score}")
1.3 注意事项
- return语句的特性:一旦执行return,函数立即结束
- 多个return的问题:函数中只能执行一个return语句
- 返回值类型:可以返回不同类型的数据
# 错误示例:多个return不会都执行
def wrong_return():
return 1 # 这个return执行后函数结束
return 2 # 这行代码永远不会执行
# 正确示例:一次返回多个值
def correct_return():
return 1, 2 # 一次性返回所有值
result = correct_return()
print(result) # 输出:(1, 2)
二、函数多种传参方式
2.1 四种参数类型概述
Python函数支持四种主要的参数传递方式:
| 参数类型 | 描述 | 特点 |
|---|---|---|
| 位置参数 | 按参数位置顺序传递 | 必须按顺序,个数匹配 |
| 关键字参数 | 使用"键=值"形式传递 | 可不按顺序,清晰明确 |
| 缺省参数 | 参数有默认值 | 可省略,有默认值 |
| 不定长参数 | 参数数量可变 | 处理不确定数量的参数 |
2.2 位置参数
位置参数:根据参数定义的位置顺序进行传递。
def user_info(name, age, gender):
"""用户信息函数"""
print(f'姓名:{name},年龄:{age},性别:{gender}')
# 正确使用:按位置顺序传递
user_info('张三', 20, '男') # 输出:姓名:张三,年龄:20,性别:男
# 错误使用:顺序错误会导致逻辑错误
user_info(20, '张三', '男') # 输出:姓名:20,年龄:张三,性别:男(逻辑错误)
位置参数特点:
- 必须按定义顺序传递参数
- 参数个数必须匹配
- 是最基本的参数传递方式
2.3 关键字参数
关键字参数:使用"参数名=值"的形式传递参数。
def user_info(name, age, gender):
"""用户信息函数"""
print(f'姓名:{name},年龄:{age},性别:{gender}')
# 使用关键字参数(顺序无关)
user_info(name='李四', age=25, gender='女')
user_info(age=25, gender='女', name='李四') # 顺序可以改变
user_info('王五', gender='男', age=30) # 混合使用,位置参数必须在前
# 输出:
# 姓名:李四,年龄:25,性别:女
# 姓名:李四,年龄:25,性别:女
# 姓名:王五,年龄:30,性别:男
关键字参数特点:
- 参数顺序可以任意
- 代码可读性更强
- 可以与位置参数混合使用(位置参数必须在前面)
2.4 缺省参数(默认参数)
缺省参数:在定义函数时给参数设置默认值。
def user_info(name, age, gender='男'):
"""用户信息函数,性别有默认值"""
print(f'姓名:{name},年龄:{age},性别:{gender}')
# 使用默认值
user_info('张三', 20) # 性别使用默认值'男'
user_info('李四', 25, '女') # 覆盖默认值
# 输出:
# 姓名:张三,年龄:20,性别:男
# 姓名:李四,年龄:25,性别:女
缺省参数规则:
- 缺省参数必须定义在非缺省参数之后
- 调用时可省略有默认值的参数
- 可以部分使用缺省参数
# 正确的定义顺序
def correct_func(a, b=10, c=20): # 正确:缺省参数在后
pass
# 错误的定义顺序
# def wrong_func(a=10, b, c=20): # 错误:缺省参数不能在非缺省参数前
# pass
2.5 不定长参数
不定长参数用于处理参数数量不确定的情况,分为两种:
2.5.1 位置传递的不定长参数(*args)
使用*收集所有位置参数为元组:
def sum_numbers(*args):
"""计算任意个数字的和"""
print(f"参数:{args},类型:{type(args)}")
return sum(args)
# 调用示例
result1 = sum_numbers(1, 2, 3) # 输出:参数:(1, 2, 3),类型:<class 'tuple'>
result2 = sum_numbers(1, 2, 3, 4, 5) # 输出:参数:(1, 2, 3, 4, 5),类型:<class 'tuple'>
result3 = sum_numbers() # 输出:参数:(),类型:<class 'tuple'>
print(f"结果1:{result1}") # 输出:6
print(f"结果2:{result2}") # 输出:15
print(f"结果3:{result3}") # 输出:0
2.5.2 关键字传递的不定长参数(**kwargs)
使用**收集所有关键字参数为字典:
def print_info(**kwargs):
"""打印任意个关键字参数"""
print(f"参数:{kwargs},类型:{type(kwargs)}")
for key, value in kwargs.items():
print(f"{key}:{value}")
# 调用示例
print_info(name='张三', age=20)
print_info(name='李四', age=25, city='北京', job='工程师')
# 输出:
# 参数:{'name': '张三', 'age': 20},类型:<class 'dict'>
# name:张三
# age:20
2.5.3 混合使用所有参数类型
def complex_func(a, b=10, *args, c=30, **kwargs):
"""混合使用所有参数类型"""
print(f"a={a}, b={b}, args={args}, c={c}, kwargs={kwargs}")
# 调用示例
complex_func(1) # a=1, b=10, args=(), c=30, kwargs={}
complex_func(1, 2) # a=1, b=2, args=(), c=30, kwargs={}
complex_func(1, 2, 3, 4, 5) # a=1, b=2, args=(3, 4, 5), c=30, kwargs={}
complex_func(1, 2, 3, 4, c=5) # a=1, b=2, args=(3, 4), c=5, kwargs={}
complex_func(1, 2, 3, 4, c=5, name='张三') # a=1, b=2, args=(3, 4), c=5, kwargs={'name': '张三'}
参数顺序规则:
- 位置参数
- 默认参数
- 不定长位置参数(*args)
- 关键字参数
- 不定长关键字参数(**kwargs)
# 标准参数顺序
def standard_func(a, b=10, *args, c=20, **kwargs):
"""标准参数顺序示例"""
pass
三、函数作为参数传递
3.1 函数作为参数的概念
在Python中,函数可以像普通数据一样作为参数传递给其他函数。
def calculate(x, y, func):
"""
计算函数
:param x: 第一个数字
:param y: 第二个数字
:param func: 计算函数
:return: 计算结果
"""
result = func(x, y) # 调用传入的函数
return result
def add(a, b):
"""加法函数"""
return a + b
def multiply(a, b):
"""乘法函数"""
return a * b
# 传递函数作为参数
result1 = calculate(10, 20, add) # 传递add函数
result2 = calculate(10, 20, multiply) # 传递multiply函数
print(f"加法结果:{result1}") # 输出:30
print(f"乘法结果:{result2}") # 输出:200
3.2 实际应用场景
3.2.1 数据处理回调
def process_data(data, process_func):
"""数据处理函数"""
print("原始数据:", data)
processed = process_func(data)
print("处理结果:", processed)
return processed
def double_list(lst):
"""将列表每个元素加倍"""
return [x * 2 for x in lst]
def square_list(lst):
"""将列表每个元素平方"""
return [x ** 2 for x in lst]
data = [1, 2, 3, 4, 5]
process_data(data, double_list) # 使用加倍函数
process_data(data, square_list) # 使用平方函数
3.2.2 排序自定义比较
def custom_sort(data, compare_func):
"""自定义排序"""
# 简化版的冒泡排序
n = len(data)
for i in range(n):
for j in range(0, n-i-1):
if compare_func(data[j], data[j+1]):
data[j], data[j+1] = data[j+1], data[j]
return data
def ascending(a, b):
"""升序比较"""
return a > b
def descending(a, b):
"""降序比较"""
return a < b
numbers = [64, 34, 25, 12, 22, 11, 90]
print("升序:", custom_sort(numbers.copy(), ascending))
print("降序:", custom_sort(numbers.copy(), descending))
3.3 优势与用途
- 逻辑传递:传递的是计算逻辑而非具体数据
- 代码复用:相同的框架处理不同的逻辑
- 灵活性:动态改变函数行为
- 回调机制:事件处理、异步编程的基础
四、匿名函数(lambda函数)
4.1 lambda函数基础
lambda函数:使用lambda关键字创建的匿名函数,适用于简单的函数功能。
# 传统函数定义
def add(x, y):
return x + y
# lambda函数定义
lambda x, y: x + y
# 使用对比
result1 = add(10, 20) # 传统函数调用
result2 = (lambda x, y: x + y)(10, 20) # lambda函数调用
print(result1, result2) # 输出:30 30
4.2 lambda函数语法
lambda 参数1, 参数2, ...: 表达式
特点:
- 没有函数名(匿名)
- 只能包含一个表达式
- 自动返回表达式结果
- 不能包含多条语句或复杂逻辑
4.3 实际应用示例
4.3.1 简单数学运算
# 定义lambda函数
square = lambda x: x ** 2
cube = lambda x: x ** 3
is_even = lambda x: x % 2 == 0
# 使用lambda函数
print(square(5)) # 输出:25
print(cube(3)) # 输出:27
print(is_even(4)) # 输出:True
print(is_even(7)) # 输出:False
4.3.2 与高阶函数配合使用
# 配合map函数
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x ** 2, numbers))
print(squares) # 输出:[1, 4, 9, 16, 25]
# 配合filter函数
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # 输出:[2, 4]
# 配合sorted函数
students = [('张三', 85), ('李四', 92), ('王五', 78)]
sorted_students = sorted(students, key=lambda x: x[1], reverse=True)
print(sorted_students) # 输出:[('李四', 92), ('张三', 85), ('王五', 78)]
4.3.3 作为函数参数传递
def calculate(x, y, operation):
"""计算函数,接受操作函数作为参数"""
return operation(x, y)
# 使用lambda作为参数
result1 = calculate(10, 5, lambda a, b: a + b) # 加法
result2 = calculate(10, 5, lambda a, b: a - b) # 减法
result3 = calculate(10, 5, lambda a, b: a * b) # 乘法
result4 = calculate(10, 5, lambda a, b: a / b if b != 0 else 0) # 除法
print(f"加:{result1}, 减:{result2}, 乘:{result3}, 除:{result4}")
4.4 lambda函数与def函数对比
| 特性 | def函数 | lambda函数 |
|---|---|---|
| 函数名 | 有名称 | 匿名 |
| 代码量 | 可多行 | 只能一行 |
| 复杂度 | 可包含复杂逻辑 | 只能简单表达式 |
| 返回值 | 需要return语句 | 自动返回表达式结果 |
| 复用性 | 可重复使用 | 通常一次性使用 |
| 可读性 | 较好 | 简单场景下清晰 |
4.5 使用建议
1适用场景:
- 简单的单行表达式
- 作为其他函数的参数
- 临时性的简单功能
- 函数式编程操作
不适用场景:
- 复杂的多行逻辑
- 需要复用的功能
- 需要文档字符串的函数
- 复杂的错误处理
# 推荐使用lambda的场景
numbers = [1, 2, 3, 4, 5]
result = list(map(lambda x: x * 2, numbers)) # 简单转换,适合lambda
# 不推荐使用lambda的场景(应使用def)
# complex_operation = lambda x: (x ** 2 if x > 0 else 0) + (x * 2 if x < 10 else x) # 太复杂,不易读
def complex_operation(x):
"""复杂的操作应该使用def函数"""
if x > 0:
result = x ** 2
else:
result = 0
if x < 10:
result += x * 2
else:
result += x
return result
五、综合实战案例
5.1 数据处理器
结合所有进阶特性,创建一个灵活的数据处理器:
def data_processor(data, *process_funcs, filter_func=None, **options):
"""
高级数据处理器
:param data: 要处理的数据
:param process_funcs: 处理函数序列
:param filter_func: 过滤函数
:param options: 配置选项
:return: 处理结果
"""
# 应用过滤函数
if filter_func:
data = list(filter(filter_func, data))
# 应用处理函数序列
for func in process_funcs:
data = [func(item) for item in data]
# 处理配置选项
if options.get('sort', False):
reverse = options.get('reverse', False)
data.sort(reverse=reverse)
if options.get('unique', False):
data = list(set(data))
return data
# 使用示例
numbers = [1, 5, 3, 8, 2, 7, 4, 6, 9, 5, 3]
# 复杂处理:过滤偶数 → 平方 → 排序 → 去重
result = data_processor(
numbers,
lambda x: x ** 2, # 平方处理
filter_func=lambda x: x % 2 == 0, # 过滤偶数
sort=True, # 排序
unique=True # 去重
)
print("原始数据:", numbers)
print("处理结果:", result)
5.2 函数组合器
创建函数组合工具,实现函数的流水线处理:
def function_composer(*funcs):
"""
函数组合器:将多个函数组合成一个流水线
:param funcs: 要组合的函数序列
:return: 组合后的函数
"""
def composed_function(data):
result = data
for func in funcs:
result = func(result)
return result
return composed_function
# 创建处理流水线
processing_pipeline = function_composer(
lambda x: x * 2, # 加倍
lambda x: x + 10, # 加10
lambda x: x ** 2, # 平方
lambda x: f"结果:{x}" # 格式化
)
# 使用流水线处理数据
result = processing_pipeline(5)
print(result) # 输出:结果:400
六、最佳实践与总结
6.1 参数使用指南
-
选择参数类型的优先级:
- 简单场景:位置参数
- 提高可读性:关键字参数
- 可选参数:缺省参数
- 参数数量不定:不定长参数
-
函数设计原则:
# 良好的函数设计 def good_design(name, age=0, *scores, city="北京", **info): """参数设计清晰合理""" pass # 不良的设计(参数混乱) # def bad_design(*args, name, age=0, **kwargs, city): # 语法错误 # pass
6.2 性能考虑
-
默认参数避免可变对象:
# 错误:默认参数使用可变对象 def bad_func(items=[]): # 每次调用使用同一个列表 items.append(1) return items # 正确:使用不可变默认值 def good_func(items=None): if items is None: items = [] items.append(1) return items -
lambda函数性能:
- 简单操作:lambda性能较好
- 复杂操作:def函数更易优化
6.3 调试技巧
-
参数检查:
def safe_divide(a, b): if not isinstance(a, (int, float)) or not isinstance(b, (int, float)): raise TypeError("参数必须是数字") if b == 0: raise ValueError("除数不能为零") return a / b -
函数签名检查:
import inspect def example(a, b=10, *args, c=20, **kwargs): pass print(inspect.signature(example)) # 输出:(a, b=10, *args, c=20, **kwargs)
通过系统学习Python函数进阶特性,您已经掌握了更高级的函数使用技巧。这些特性让函数更加灵活和强大,是编写高质量Python代码的关键。多加练习,在实际项目中灵活运用这些特性,将大幅提升您的编程能力。

浙公网安备 33010602011771号