在Python编程中,函数就像乐高积木------你可以创建小块的功能模块,然后将它们组合成复杂的结构。今天,让我们深入探索Python函数的方方面面,从最基础的函数定义到高级的装饰器模式。
引入:为什么函数如此重要?
想象一下,你正在编写一个数据分析程序:
- 需要多次计算数据的平均值
- 需要格式化输出结果
- 需要验证输入数据的有效性
如果没有函数,你会重复写相同的代码。而使用函数,就像拥有一个魔法工具箱,每个工具都有特定的用途,可以反复使用,让代码更简洁、更易维护。
一、函数基础:构建代码模块
1.1 函数的定义与调用
python
# 函数基础:定义、调用、返回值
print("=== Python函数基础 ===\n")
# 1. 最简单的函数
def greet():
"""一个简单的问候函数"""
print("你好!")
print("欢迎学习Python函数")
# 调用函数
greet()
# 2. 带参数的函数
def personalized_greet(name):
"""向特定的人问好"""
print(f"你好,{name}!")
print(f"{name},今天过得怎么样?")
# 调用带参数的函数
personalized_greet("小明")
personalized_greet("小红")
# 3. 带返回值的函数
def add_numbers(a, b):
"""返回两个数的和"""
result = a + b
return result
# 使用返回值
sum_result = add_numbers(5, 3)
print(f"5 + 3 = {sum_result}")
# 返回值可以直接使用
print(f"10 + 20 = {add_numbers(10, 20)}")
# 4. 多个返回值
def get_student_info():
"""返回学生的姓名、年龄和成绩"""
name = "张三"
age = 18
scores = [85, 92, 78]
return name, age, scores # 实际上返回一个元组
# 接收多个返回值
student_name, student_age, student_scores = get_student_info()
print(f"学生信息:{student_name},{student_age}岁,成绩:{student_scores}")
# 5. 查看函数信息
print(f"\n函数文档:{add_numbers.__doc__}")
print(f"函数名:{add_numbers.__name__}")
print(f"模块:{add_numbers.__module__}")
1.2 参数传递的四种方式
python
print("\n=== 参数传递的四种方式 ===\n")
# 1. 位置参数(最基本的参数传递)
def describe_pet(animal_type, pet_name):
"""显示宠物的信息"""
print(f"我有一只{animal_type},它叫{pet_name}。")
describe_pet("狗", "旺财") # 参数按位置传递
describe_pet("猫", "咪咪")
# 2. 关键字参数(指定参数名)
describe_pet(animal_type="仓鼠", pet_name="吱吱") # 明确指定参数名
describe_pet(pet_name="花花", animal_type="鸟") # 顺序可以改变
# 3. 默认参数(参数有默认值)
def make_coffee(size="中杯", coffee_type="拿铁", sugar=True):
"""制作咖啡"""
sugar_text = "加糖" if sugar else "不加糖"
print(f"制作一杯{size}{coffee_type},{sugar_text}")
make_coffee() # 使用所有默认值
make_coffee("大杯") # 只指定第一个参数
make_coffee(coffee_type="美式", sugar=False) # 指定部分参数
# 4. 可变参数(参数数量可变)
def calculate_average(*scores):
"""计算平均分,可以接受任意数量的分数"""
if len(scores) == 0:
return 0
total = sum(scores)
return total / len(scores)
print(f"平均分1:{calculate_average(85, 90, 78):.2f}")
print(f"平均分2:{calculate_average(92, 88, 95, 76):.2f}")
print(f"平均分3:{calculate_average(100, 95):.2f}")
# 5. 关键字可变参数(**kwargs)
def build_profile(first, last, **user_info):
"""创建一个包含用户所有信息的字典"""
profile = {}
profile['first_name'] = first
profile['last_name'] = last
for key, value in user_info.items():
profile[key] = value
return profile
user_profile = build_profile('张', '三', age=25, city='北京', job='工程师')
print(f"\n用户档案:{user_profile}")
# 6. 参数组合使用(完整的函数签名)
def complex_function(a, b, *args, c=10, d=20, **kwargs):
"""演示所有参数类型的组合"""
print(f"a={a}, b={b}, args={args}, c={c}, d={d}, kwargs={kwargs}")
# 调用示例
complex_function(1, 2, 3, 4, 5, c=30, e=100, f=200)
二、函数进阶:作用域与闭包
2.1 变量作用域
python
print("=== 变量作用域:理解Python的命名空间 ===\n")
# 全局变量(在整个文件中都有效)
global_var = "我是全局变量"
def scope_demo():
"""演示变量作用域"""
# 局部变量(只在函数内部有效)
local_var = "我是局部变量"
# 可以在函数内部访问全局变量
print(f"函数内访问全局变量:{global_var}")
print(f"函数内访问局部变量:{local_var}")
# 修改全局变量需要使用global关键字
global global_var
global_var = "全局变量已被修改"
# 嵌套作用域
def inner_function():
# 内层函数可以访问外层函数的变量
inner_var = "我是内层局部变量"
print(f"\n内层函数:")
print(f" 访问外层局部变量:{local_var}")
print(f" 访问全局变量:{global_var}")
print(f" 访问内层局部变量:{inner_var}")
# 使用nonlocal修改外层函数的变量
nonlocal local_var
local_var = "外层局部变量已被内层函数修改"
inner_function()
print(f"\n外层函数修改后:local_var = {local_var}")
# 函数调用
print(f"函数调用前全局变量:{global_var}")
scope_demo()
print(f"函数调用后全局变量:{global_var}")
# 尝试访问局部变量(会报错)
try:
print(local_var)
except NameError as e:
print(f"\n错误:{e} - 不能从外部访问局部变量")
print("\n=== 作用域查找规则:LEGB ===")
print("1. Local(局部作用域) - 函数内部")
print("2. Enclosing(嵌套作用域) - 外层函数")
print("3. Global(全局作用域) - 模块级别")
print("4. Built-in(内置作用域) - Python内置函数和变量")
2.2 闭包:函数中的函数
python
print("\n=== 闭包:函数返回函数 ===")
# 闭包:函数内部定义了另一个函数,并且内部函数引用了外部函数的变量
def outer_function(message):
"""外部函数"""
def inner_function():
"""内部函数(闭包)"""
print(f"消息:{message}")
return inner_function # 返回内部函数,而不是调用它
# 创建闭包
closure = outer_function("你好,闭包!")
closure() # 调用闭包函数
print("\n=== 闭包的实际应用:计数器 ===")
def create_counter():
"""创建一个计数器闭包"""
count = 0 # 这个变量会被闭包"记住"
def counter():
nonlocal count # 声明使用外层函数的变量
count += 1
return count
return counter
# 创建两个独立的计数器
counter1 = create_counter()
counter2 = create_counter()
print(f"计数器1:{counter1()}") # 1
print(f"计数器1:{counter1()}") # 2
print(f"计数器2:{counter2()}") # 1
print(f"计数器1:{counter1()}") # 3
print(f"计数器2:{counter2()}") # 2
print("\n=== 闭包应用:函数工厂 ===")
def power_factory(exponent):
"""创建计算幂的函数工厂"""
def power(base):
return base ** exponent
return power
# 创建不同的幂函数
square = power_factory(2) # 平方函数
cube = power_factory(3) # 立方函数
print(f"3的平方:{square(3)}") # 9
print(f"3的立方:{cube(3)}") # 27
print(f"5的平方:{square(5)}") # 25
print("\n=== 闭包应用:配置函数 ===")
def make_multiplier(factor):
"""创建乘以特定因子的函数"""
def multiplier(x):
return x * factor
return multiplier
# 创建不同的乘法器
double = make_multiplier(2)
triple = make_multiplier(3)
ten_times = make_multiplier(10)
print(f"2倍:{double(5)}") # 10
print(f"3倍:{triple(5)}") # 15
print(f"10倍:{ten_times(5)}") # 50
三、装饰器:函数的"化妆师"
3.1 装饰器基础
python
print("=== 装饰器基础:增强函数功能 ===")
# 装饰器本质上是一个函数,它接受一个函数作为参数,返回一个新的函数
def simple_decorator(func):
"""一个简单的装饰器"""
def wrapper():
print("装饰器:函数执行前")
result = func()
print("装饰器:函数执行后")
return result
return wrapper
@simple_decorator
def say_hello():
"""被装饰的函数"""
print("你好,世界!")
# 调用被装饰的函数
print("调用被装饰的函数:")
say_hello()
print("\n=== 手动应用装饰器 ===")
def greet():
"""普通函数"""
print("你好!")
# 不适用@语法,手动装饰
decorated_greet = simple_decorator(greet)
print("手动装饰的函数:")
decorated_greet()
print("\n=== 带参数的函数装饰 ===")
def logger_decorator(func):
"""记录函数调用的装饰器"""
def wrapper(*args, **kwargs):
print(f"调用函数:{func.__name__}")
print(f"参数:args={args}, kwargs={kwargs}")
result = func(*args, **kwargs)
print(f"返回值:{result}")
return result
return wrapper
@logger_decorator
def add(a, b):
"""两个数相加"""
return a + b
@logger_decorator
def greet_person(name, title="先生"):
"""问候某人"""
return f"你好,{name}{title}!"
# 测试带参数的装饰器
print("测试加法函数:")
result = add(3, 5)
print(f"最终结果:{result}\n")
print("测试问候函数:")
greeting = greet_person("小明", title="同学")
print(f"最终问候:{greeting}")
3.2 实用的装饰器示例
python
print("\n=== 实用装饰器示例 ===")
import time
import functools
# 1. 计时装饰器
def timer_decorator(func):
"""计算函数执行时间的装饰器"""
@functools.wraps(func) # 保留原函数的元数据
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} 执行时间:{end_time - start_time:.4f}秒")
return result
return wrapper
@timer_decorator
def slow_function(seconds):
"""模拟耗时操作"""
time.sleep(seconds)
return f"等待了{seconds}秒"
print("计时装饰器测试:")
print(slow_function(1))
# 2. 缓存装饰器(记忆化)
def cache_decorator(func):
"""缓存函数结果的装饰器"""
cache = {}
@functools.wraps(func)
def wrapper(*args):
if args in cache:
print(f"缓存命中:{args} -> {cache[args]}")
return cache[args]
result = func(*args)
cache[args] = result
print(f"缓存未命中,计算结果:{args} -> {result}")
return result
return wrapper
@cache_decorator
def fibonacci(n):
"""计算斐波那契数列(递归实现)"""
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print("\n缓存装饰器测试(斐波那契数列):")
print(f"fibonacci(5) = {fibonacci(5)}")
print(f"fibonacci(5) = {fibonacci(5)}") # 第二次调用应该从缓存获取
# 3. 重试装饰器
def retry_decorator(max_attempts=3, delay=1):
"""重试装饰器,失败时自动重试"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
last_exception = None
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
last_exception = e
if attempt < max_attempts - 1:
print(f"第{attempt+1}次尝试失败:{e},{delay}秒后重试...")
time.sleep(delay)
print(f"所有{max_attempts}次尝试都失败了")
raise last_exception
return wrapper
return decorator
@retry_decorator(max_attempts=3, delay=1)
def unreliable_function():
"""有时会失败的函数"""
import random
if random.random() < 0.7: # 70%的几率失败
raise ValueError("随机失败")
return "成功!"
print("\n重试装饰器测试:")
try:
result = unreliable_function()
print(f"结果:{result}")
except Exception as e:
print(f"最终失败:{e}")
3.3 带参数的装饰器
python
print("\n=== 带参数的装饰器 ===")
def repeat_decorator(num_times):
"""重复执行函数的装饰器"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
results = []
for i in range(num_times):
print(f"第{i+1}次执行:")
result = func(*args, **kwargs)
results.append(result)
return results
return wrapper
return decorator
@repeat_decorator(num_times=3)
def greet(name):
"""问候函数"""
return f"你好,{name}!"
print("带参数的装饰器测试:")
results = greet("小明")
print(f"所有结果:{results}")
print("\n=== 多个装饰器 ===")
def decorator1(func):
def wrapper():
print("装饰器1:之前")
func()
print("装饰器1:之后")
return wrapper
def decorator2(func):
def wrapper():
print("装饰器2:之前")
func()
print("装饰器2:之后")
return wrapper
@decorator1
@decorator2
def say_hi():
print("你好!")
print("多个装饰器测试:")
say_hi()
print("\n注意:装饰器的应用顺序是从下往上(从里到外)")
四、Lambda函数与高阶函数
4.1 Lambda表达式
python
print("=== Lambda表达式:匿名函数 ===")
# Lambda表达式用于创建简单的匿名函数
# 语法:lambda 参数: 表达式
# 1. 基本用法
square = lambda x: x ** 2
print(f"平方函数:square(5) = {square(5)}")
add = lambda a, b: a + b
print(f"加法函数:add(3, 4) = {add(3, 4)}")
# 2. 立即调用
result = (lambda x, y: x * y)(3, 4)
print(f"立即调用:(lambda x, y: x * y)(3, 4) = {result}")
# 3. 在列表推导式中使用
numbers = [1, 2, 3, 4, 5]
squares = [(lambda x: x ** 2)(x) for x in numbers]
print(f"列表推导式中的Lambda:{squares}")
print("\n=== Lambda的典型应用场景 ===")
# 1. 排序
students = [
{"name": "小明", "score": 85},
{"name": "小红", "score": 92},
{"name": "小刚", "score": 78}
]
# 按分数排序
students_sorted = sorted(students, key=lambda s: s["score"], reverse=True)
print("按分数排序:")
for student in students_sorted:
print(f" {student['name']}: {student['score']}分")
# 2. 过滤
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(f"\n偶数:{even_numbers}")
# 3. 映射
squared_numbers = list(map(lambda x: x ** 2, numbers))
print(f"平方数:{squared_numbers}")
# 4. 在GUI编程中(如按钮回调)
print("\nLambda作为回调函数的示例:")
def button_click(button_name):
return lambda: print(f"{button_name} 被点击了")
ok_button = button_click("确定")
cancel_button = button_click("取消")
# 模拟点击
ok_button()
cancel_button()
4.2 高阶函数
python
print("\n=== 高阶函数:函数作为参数或返回值 ===")
# 1. 函数作为参数
def apply_operation(numbers, operation):
"""对列表中的每个数应用操作"""
return [operation(x) for x in numbers]
numbers = [1, 2, 3, 4, 5]
def square(x):
return x ** 2
def double(x):
return x * 2
print(f"应用平方操作:{apply_operation(numbers, square)}")
print(f"应用加倍操作:{apply_operation(numbers, double)}")
print(f"应用Lambda操作:{apply_operation(numbers, lambda x: x + 10)}")
# 2. 函数作为返回值
def make_adder(n):
"""创建加法函数"""
def adder(x):
return x + n
return adder
add5 = make_adder(5)
add10 = make_adder(10)
print(f"add5(3) = {add5(3)}")
print(f"add10(3) = {add10(3)}")
# 3. 函数组合
def compose(f, g):
"""组合两个函数:f(g(x))"""
return lambda x: f(g(x))
def add_one(x):
return x + 1
def multiply_by_two(x):
return x * 2
# 创建组合函数:先加1,再乘以2
add_then_multiply = compose(multiply_by_two, add_one)
print(f"add_then_multiply(3) = {add_then_multiply(3)}") # (3+1)*2 = 8
# 4. 部分函数
from functools import partial
def power(base, exponent):
"""计算幂"""
return base ** exponent
# 创建平方函数(固定exponent为2)
square = partial(power, exponent=2)
print(f"square(5) = {square(5)}")
# 创建立方函数(固定exponent为3)
cube = partial(power, exponent=3)
print(f"cube(3) = {cube(3)}")
五、生成器函数:惰性计算的艺术
5.1 yield关键字与生成器
python
print("=== 生成器函数:使用yield ===")
# 生成器函数使用yield返回一个值,并暂停执行,下次从暂停处继续
def simple_generator():
"""一个简单的生成器"""
print("开始")
yield 1
print("继续")
yield 2
print("结束")
yield 3
print("创建生成器:")
gen = simple_generator()
print("第一次调用next:")
print(next(gen))
print("第二次调用next:")
print(next(gen))
print("第三次调用next:")
print(next(gen))
# 再次调用会抛出StopIteration异常
try:
print(next(gen))
except StopIteration:
print("生成器已结束")
print("\n=== 使用for循环遍历生成器 ===")
def countdown(n):
"""倒数生成器"""
while n > 0:
yield n
n -= 1
print("倒数:")
for number in countdown(5):
print(f"倒计时:{number}")
print("\n=== 生成器表达式 ===")
# 生成器表达式类似于列表推导式,但使用圆括号
numbers = [1, 2, 3, 4, 5]
# 列表推导式:立即计算所有值
squares_list = [x**2 for x in numbers]
print(f"列表推导式:{squares_list},类型:{type(squares_list)}")
# 生成器表达式:惰性计算
squares_gen = (x**2 for x in numbers)
print(f"生成器表达式:{squares_gen},类型:{type(squares_gen)}")
print(f"转换为列表:{list(squares_gen)}")
5.2 生成器的实际应用
python
print("\n=== 生成器的实际应用 ===")
# 1. 读取大文件
def read_large_file(file_path):
"""逐行读取大文件"""
with open(file_path, 'r', encoding='utf-8') as file:
for line in file:
yield line.strip()
# 模拟大文件
with open('large_file.txt', 'w', encoding='utf-8') as f:
for i in range(1000):
f.write(f"这是第{i+1}行数据\n")
print("读取大文件(不占用太多内存):")
line_count = 0
for line in read_large_file('large_file.txt'):
if line_count < 5: # 只显示前5行
print(f" {line}")
line_count += 1
print(f"总行数:{line_count}")
# 2. 无限序列
def fibonacci_sequence():
"""生成斐波那契数列(无限)"""
a, b = 0, 1
while True:
yield a
a, b = b, a + b
print("\n斐波那契数列(前10个):")
fib_gen = fibonacci_sequence()
for i in range(10):
print(f" F{i} = {next(fib_gen)}")
# 3. 管道处理
def number_generator(n):
"""生成数字"""
for i in range(n):
yield i
def square_numbers(numbers):
"""平方数字"""
for num in numbers:
yield num ** 2
def filter_even(numbers):
"""过滤偶数"""
for num in numbers:
if num % 2 == 0:
yield num
print("\n管道处理:生成 → 平方 → 过滤")
pipeline = filter_even(square_numbers(number_generator(10)))
print(f"结果:{list(pipeline)}")
# 4. 协程(双向通信)
def coroutine_example():
"""一个简单的协程"""
print("协程启动")
while True:
value = yield # 接收值
print(f"收到值:{value}")
yield value * 2 # 返回值
print("\n协程示例:")
coro = coroutine_example()
next(coro) # 启动协程,执行到第一个yield
print(f"发送10,收到:{coro.send(10)}")
next(coro) # 继续到下一个yield
print(f"发送20,收到:{coro.send(20)}")
六、面向对象中的函数:方法与特殊方法
6.1 类方法与实例方法
python
print("=== 类中的函数:方法 ===")
class Calculator:
"""计算器类"""
# 类属性
operation_count = 0
def __init__(self, name="计算器"):
"""构造方法"""
self.name = name
self.history = []
# 实例方法:操作实例数据
def add(self, a, b):
"""加法"""
Calculator.operation_count += 1
result = a + b
self.history.append(f"{a} + {b} = {result}")
return result
def multiply(self, a, b):
"""乘法"""
Calculator.operation_count += 1
result = a * b
self.history.append(f"{a} × {b} = {result}")
return result
# 实例方法:访问实例数据
def show_history(self):
"""显示历史记录"""
if not self.history:
print(f"{self.name} 还没有操作记录")
else:
print(f"{self.name} 的操作记录:")
for operation in self.history:
print(f" {operation}")
# 类方法:操作类数据
@classmethod
def get_operation_count(cls):
"""获取总操作次数"""
return cls.operation_count
# 静态方法:不访问类或实例数据
@staticmethod
def help():
"""显示帮助信息"""
return "这是一个计算器类,支持加法和乘法运算"
print("创建计算器实例:")
calc1 = Calculator("我的计算器")
print("\n使用实例方法:")
print(f"5 + 3 = {calc1.add(5, 3)}")
print(f"5 × 3 = {calc1.multiply(5, 3)}")
calc1.show_history()
print("\n使用类方法:")
print(f"总操作次数:{Calculator.get_operation_count()}")
print("\n使用静态方法:")
print(f"帮助信息:{Calculator.help()}")
print("\n创建第二个计算器:")
calc2 = Calculator("第二个计算器")
print(f"10 + 20 = {calc2.add(10, 20)}")
print(f"总操作次数(类级别):{Calculator.get_operation_count()}")
6.2 特殊方法(魔术方法)
python
print("\n=== 特殊方法(魔术方法) ===")
class Vector:
"""向量类,演示特殊方法"""
def __init__(self, x, y):
self.x = x
self.y = y
# 字符串表示
def __str__(self):
"""str() 时调用"""
return f"Vector({self.x}, {self.y})"
def __repr__(self):
"""repr() 时调用"""
return f"Vector({self.x}, {self.y})"
# 算术运算
def __add__(self, other):
"""+ 运算"""
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
"""- 运算"""
return Vector(self.x - other.x, self.y - other.y)
def __mul__(self, scalar):
"""* 运算(向量乘以标量)"""
return Vector(self.x * scalar, self.y * scalar)
# 比较运算
def __eq__(self, other):
"""== 运算"""
return self.x == other.x and self.y == other.y
def __lt__(self, other):
"""< 运算(比较长度)"""
return (self.x**2 + self.y**2) < (other.x**2 + other.y**2)
# 长度和布尔值
def __len__(self):
"""len() 时调用(返回维度)"""
return 2
def __bool__(self):
"""bool() 时调用"""
return self.x != 0 or self.y != 0
# 调用对象
def __call__(self, scale=1):
"""对象被调用时"""
return Vector(self.x * scale, self.y * scale)
print("创建向量:")
v1 = Vector(3, 4)
v2 = Vector(1, 2)
print(f"v1 = {v1}")
print(f"v2 = {v2}")
print(f"\nv1 + v2 = {v1 + v2}")
print(f"v1 - v2 = {v1 - v2}")
print(f"v1 * 2 = {v1 * 2}")
print(f"\nv1 == v2: {v1 == v2}")
print(f"v1 < v2: {v1 < v2}")
print(f"\nlen(v1): {len(v1)}")
print(f"bool(v1): {bool(v1)}")
print(f"\nv1(2): {v1(2)}") # 调用对象
print("\n=== 属性访问特殊方法 ===")
class Person:
"""演示属性访问特殊方法"""
def __init__(self, name, age):
self.name = name
self._age = age # 私有属性
# 属性访问
def __getattr__(self, name):
"""访问不存在的属性时调用"""
print(f"__getattr__: 尝试访问不存在的属性 '{name}'")
return None
def __setattr__(self, name, value):
"""设置属性时调用"""
if name == '_age' and value < 0:
print("年龄不能为负数!")
return
print(f"__setattr__: 设置属性 {name} = {value}")
super().__setattr__(name, value)
def __delattr__(self, name):
"""删除属性时调用"""
if name == 'name':
print("不能删除姓名属性!")
return
print(f"__delattr__: 删除属性 {name}")
super().__delattr__(name)
person = Person("小明", 25)
print(f"姓名:{person.name}")
print(f"年龄:{person._age}")
person.salary = 5000 # 设置新属性
print(f"薪水:{person.salary}")
print(f"不存在的属性:{person.address}") # 访问不存在的属性
del person.salary # 删除属性
print(f"删除后:{person.salary}")
七、实战应用:函数式数据处理管道
python
print("\n=== 实战:函数式数据处理管道 ===")
# 创建示例数据
students = [
{"name": "张三", "age": 18, "scores": {"math": 85, "english": 92, "chinese": 78}},
{"name": "李四", "age": 17, "scores": {"math": 92, "english": 88, "chinese": 95}},
{"name": "王五", "age": 19, "scores": {"math": 76, "english": 85, "chinese": 90}},
{"name": "赵六", "age": 18, "scores": {"math": 88, "english": 92, "chinese": 86}},
{"name": "钱七", "age": 17, "scores": {"math": 95, "english": 79, "chinese": 88}},
]
# 1. 纯函数:不修改外部状态,相同输入总是得到相同输出
def calculate_average(student):
"""计算学生的平均分"""
scores = student["scores"].values()
return sum(scores) / len(scores)
def add_average(student):
"""添加平均分到学生信息(返回新字典)"""
student_copy = student.copy()
student_copy["average"] = calculate_average(student)
return student_copy
# 2. 高阶函数:处理数据管道
def process_students(students, *processors):
"""处理学生数据管道"""
result = students
for processor in processors:
result = processor(result)
return result
# 3. 数据处理函数
def add_average_to_all(students):
"""为所有学生添加平均分"""
return list(map(add_average, students))
def filter_by_age(students, min_age=18):
"""过滤年龄"""
return list(filter(lambda s: s["age"] >= min_age, students))
def sort_by_average(students, reverse=True):
"""按平均分排序"""
return sorted(students, key=lambda s: s.get("average", 0), reverse=reverse)
def get_top_n(students, n=3):
"""获取前N名学生"""
return students[:n]
def format_output(students):
"""格式化输出"""
return [f"{s['name']}({s['age']}岁): 平均分{s['average']:.1f}" for s in students]
# 4. 组合函数
from functools import partial
# 创建部分函数
filter_adults = partial(filter_by_age, min_age=18)
get_top_3 = partial(get_top_n, n=3)
# 5. 构建数据处理管道
print("数据处理管道:添加平均分 → 过滤成年人 → 按平均分排序 → 取前三名")
result = process_students(
students,
add_average_to_all,
filter_adults,
lambda s: sort_by_average(s, reverse=True),
get_top_3,
format_output
)
print("\n结果:")
for i, student in enumerate(result, 1):
print(f" {i}. {student}")
# 6. 使用装饰器记录处理步骤
def log_step(step_name):
"""记录处理步骤的装饰器"""
def decorator(func):
def wrapper(students):
print(f"步骤:{step_name} (处理{len(students)}名学生)")
result = func(students)
print(f" 结果:{len(result)}名学生")
return result
return wrapper
return decorator
print("\n=== 带日志的数据处理管道 ===")
@log_step("添加平均分")
def add_average_with_log(students):
return add_average_to_all(students)
@log_step("过滤成年人")
def filter_adults_with_log(students):
return filter_adults(students)
@log_step("按平均分排序")
def sort_by_average_with_log(students):
return sort_by_average(students, reverse=True)
@log_step("取前三名")
def get_top_3_with_log(students):
return get_top_3(students)
final_result = process_students(
students,
add_average_with_log,
filter_adults_with_log,
sort_by_average_with_log,
get_top_3_with_log,
format_output
)
print("\n最终结果:")
for i, student in enumerate(final_result, 1):
print(f" {i}. {student}")
八、总结:Python函数的核心要点
🎯 核心要点总结:
-
函数定义 :使用
def关键字,可以带参数和返回值pythondef function_name(parameters): """文档字符串""" # 函数体 return value -
四种参数类型:
- 位置参数:按顺序传递
- 关键字参数:指定参数名
- 默认参数:参数有默认值
- 可变参数 :
*args和**kwargs
-
装饰器:增强函数功能的强大工具
python@decorator def function(): pass -
Lambda表达式:匿名函数,简洁高效
pythonlambda x: x**2 -
生成器 :使用
yield,节省内存pythondef generator(): yield value -
闭包:函数中的函数,可以"记住"外部变量
💡 最佳实践:
-
一个函数只做一件事:保持函数简洁,功能单一
-
使用有意义的函数名:函数名应该描述函数的功能
-
编写文档字符串:解释函数的作用、参数和返回值
-
使用类型提示(Python 3.5+):提高代码可读性
pythondef add(a: int, b: int) -> int: return a + b -
避免副作用:纯函数更容易测试和维护