1. Python函数基础:从零开始理解函数概念
作为一名Python开发者,我经常遇到初学者对函数概念理解不够深入的问题。函数确实是Python编程中最基础也最重要的概念之一,它就像是我们日常生活中的工具包,把常用的操作封装起来,随时可以取用。
1.1 什么是函数?
简单来说,函数就是一段组织好的、可重复使用的代码块。想象一下,如果你每天都要计算不同数字的平方,与其每次都写x*x,不如把它封装成一个函数,这样既方便又不容易出错。
函数在Python中有几个关键特点:
- 模块化:把复杂任务分解成小任务
- 可重用:一次定义,多次调用
- 隔离性:函数内部变量不影响外部
- 抽象性:使用者不需要知道内部实现
1.2 为什么需要函数?
在我多年的编程经验中,发现使用函数至少有五大好处:
- 代码复用:避免重复编写相同逻辑
- 提高可读性:良好命名的函数本身就是注释
- 便于维护:修改只需调整一处
- 降低复杂度:分解大问题为小问题
- 团队协作:不同开发者可以分工编写不同函数
提示:良好的函数应该像黑盒子一样工作 - 使用者只需要知道输入什么、输出什么,而不需要关心内部如何实现。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 函数定义与基本结构
2.1 定义函数的语法
Python中使用def关键字定义函数,基本语法如下:
python复制def 函数名(参数1, 参数2, ...):
"""文档字符串(可选)"""
函数体
return 返回值(可选)
让我们拆解这个结构:
def:定义函数的关键字函数名:遵循变量命名规则,最好使用小写字母和下划线():包含参数列表,可以为空::表示函数头结束文档字符串:用三引号包裹,描述函数用途(强烈建议添加)函数体:缩进的代码块return:返回结果(可选)
2.2 第一个函数示例
让我们创建一个计算圆面积的函数:
python复制def calculate_circle_area(radius):
"""计算圆的面积
参数:
radius (float): 圆的半径
返回:
float: 圆的面积
"""
pi = 3.14159
area = pi * radius ** 2
return area
这个例子展示了良好函数应有的元素:
- 清晰的函数名(动词+名词)
- 详细的文档字符串
- 明确的参数
- 具体的返回值
2.3 函数命名最佳实践
根据PEP 8风格指南,函数命名应遵循:
- 使用小写字母和下划线(snake_case)
- 使用动词或动词短语
- 保持简短但描述性
- 避免使用内置函数名
好的命名示例:
get_user_inputcalculate_averageprocess_data
坏的命名示例:
foo(太模糊)CalculateAverage(不应使用大写)print(覆盖内置函数)
3. 函数参数详解
参数是函数与外界交互的接口,Python提供了多种参数传递方式,灵活掌握这些方式能让你写出更优雅的代码。
3.1 位置参数
位置参数是最基本的参数类型,调用时按照定义顺序传递:
python复制def greet(name, message):
print(f"{message}, {name}!")
greet("Alice", "Hello") # 输出: Hello, Alice!
注意事项:
- 必须按顺序提供所有位置参数
- 缺少参数会引发TypeError
- 多出参数也会引发TypeError
3.2 关键字参数
关键字参数通过参数名指定,顺序不重要:
python复制greet(message="Hi", name="Bob") # 输出: Hi, Bob!
优点:
- 提高代码可读性
- 参数顺序不重要
- 与默认参数配合使用更灵活
3.3 默认参数
默认参数允许你为参数指定默认值:
python复制def greet(name, message="Hello"):
print(f"{message}, {name}!")
greet("Charlie") # 输出: Hello, Charlie!
重要规则:
- 默认参数必须放在非默认参数后面
- 默认参数在函数定义时计算,而非调用时
- 避免使用可变对象作为默认值(如列表、字典)
注意:默认参数值只会在函数定义时计算一次,这会导致一个常见陷阱:
python复制def add_item(item, items=[]):
items.append(item)
return items
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] 而不是预期的[2]
正确做法是使用None作为默认值:
python复制def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
3.4 可变参数
Python提供了两种可变参数机制,用于处理不确定数量的参数。
3.4.1 *args - 接收任意数量位置参数
*args将接收的所有位置参数打包成元组:
python复制def sum_numbers(*args):
print(f"参数类型: {type(args)}") # <class 'tuple'>
return sum(args)
print(sum_numbers(1, 2, 3)) # 6
print(sum_numbers(1, 2, 3, 4, 5)) # 15
使用场景:
- 需要处理不定数量参数时
- 函数参数需要传递给另一个函数时
3.4.2 **kwargs - 接收任意数量关键字参数
**kwargs将接收的所有关键字参数打包成字典:
python复制def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_info(name="Alice", age=25, city="New York")
# 输出:
# name: Alice
# age: 25
# city: New York
使用场景:
- 需要处理配置选项时
- 实现装饰器时
- 需要将参数传递给其他函数时
3.5 参数组合使用规则
当多种参数类型混合使用时,必须遵循以下顺序:
- 位置参数
- 默认参数
- *args
- **kwargs
示例:
python复制def complex_func(a, b=2, *args, **kwargs):
print(f"a: {a}, b: {b}")
print(f"args: {args}")
print(f"kwargs: {kwargs}")
complex_func(1, 3, 4, 5, 6, x=7, y=8)
# 输出:
# a: 1, b: 3
# args: (4, 5, 6)
# kwargs: {'x': 7, 'y': 8}
4. 返回值与函数作用
返回值是函数与调用者通信的主要方式,理解返回值的使用对编写清晰代码至关重要。
4.1 return语句详解
return语句用于结束函数执行并返回结果:
python复制def add(a, b):
return a + b
result = add(3, 4) # result = 7
关键点:
- 可以返回任意Python对象
- 可以返回多个值(实际上是返回一个元组)
- 执行return后函数立即终止
- 没有return或return后无值则返回None
4.2 返回多个值
Python函数可以"返回多个值",实际上是返回一个元组:
python复制def min_max(numbers):
return min(numbers), max(numbers)
smallest, largest = min_max([3, 1, 4, 1, 5, 9, 2])
print(smallest) # 1
print(largest) # 9
实际应用:
- 需要返回多个相关值时
- 状态和结果需要同时返回时
- 简化需要返回复杂结构的代码
4.3 无返回值函数
没有return语句或只有return的函数返回None:
python复制def greet(name):
print(f"Hello, {name}!")
result = greet("Alice") # Hello, Alice!
print(result) # None
设计建议:
- 明确区分"命令"函数(执行操作)和"查询"函数(返回信息)
- 避免既修改状态又返回值的函数(除非有充分理由)
- 对于只执行操作的函数,可以省略return或明确return None
4.4 提前返回
函数可以在任何位置使用return提前结束:
python复制def find_first_even(numbers):
for num in numbers:
if num % 2 == 0:
return num
return None # 没有偶数时返回None
优点:
- 简化嵌套条件逻辑
- 提高代码可读性
- 减少不必要的变量和嵌套
5. 变量作用域与生命周期
理解变量作用域是避免bug的关键,Python的作用域规则相对简单但有一些需要注意的地方。
5.1 LEGB规则
Python查找变量的顺序遵循LEGB规则:
- Local(局部) - 当前函数内部
- Enclosing(闭包) - 嵌套函数的外层函数
- Global(全局) - 模块级别
- Built-in(内置) - Python内置名称
python复制x = "global" # Global
def outer():
x = "outer" # Enclosing
def inner():
x = "inner" # Local
print(x)
inner()
outer() # 输出: inner
5.2 全局变量与global关键字
函数内部默认不能直接修改全局变量:
python复制count = 0
def increment():
count += 1 # UnboundLocalError
increment()
需要使用global关键字声明:
python复制count = 0
def increment():
global count
count += 1
increment()
print(count) # 1
最佳实践:
- 尽量避免使用全局变量
- 如果必须使用,考虑用类封装
- 全局变量用全大写命名(如CONFIG)
- 在多线程环境中要特别小心全局变量
5.3 nonlocal关键字
对于嵌套函数,使用nonlocal可以修改外层函数的变量:
python复制def outer():
x = "original"
def inner():
nonlocal x
x = "modified"
inner()
print(x) # 输出: modified
outer()
使用场景:
- 实现闭包时
- 需要维护函数间的状态时
- 替代简单的类实现
5.4 作用域陷阱
5.4.1 循环变量泄漏
Python中for循环的变量会泄漏到外部作用域:
python复制for i in range(3):
pass
print(i) # 2 而不是报错
5.4.2 列表推导式的作用域
Python 3中列表推导式有自己的作用域:
python复制x = "global"
values = [x for x in range(3)]
print(x) # "global" (Python 3), 但在Python 2中会是2
6. Lambda表达式(匿名函数)
Lambda表达式是创建小型匿名函数的快捷方式,适合简单的操作。
6.1 基本语法
python复制lambda 参数: 表达式
示例:
python复制square = lambda x: x * x
print(square(5)) # 25
6.2 与常规函数的区别
- 没有函数名(除非赋值给变量)
- 只能包含单个表达式
- 没有语句(如if、for等)
- 自动返回表达式结果
- 通常用于高阶函数中
6.3 常见使用场景
6.3.1 排序
python复制students = [
{"name": "Alice", "grade": 89},
{"name": "Bob", "grade": 72},
{"name": "Charlie", "grade": 93}
]
students.sort(key=lambda s: s["grade"])
print(students)
# 输出: [{'name': 'Bob', 'grade': 72}, {'name': 'Alice', 'grade': 89}, {'name': 'Charlie', 'grade': 93}]
6.3.2 过滤
python复制numbers = [1, 2, 3, 4, 5, 6]
even = list(filter(lambda x: x % 2 == 0, numbers))
print(even) # [2, 4, 6]
6.3.3 映射
python复制numbers = [1, 2, 3, 4]
squares = list(map(lambda x: x ** 2, numbers))
print(squares) # [1, 4, 9, 16]
6.4 限制与替代方案
Lambda表达式虽然方便,但有以下限制:
- 可读性差(复杂的lambda难以理解)
- 不能包含语句或注解
- 调试困难(没有函数名)
对于复杂操作,建议使用常规函数:
python复制# 不推荐
process = lambda x: x**2 if x > 0 else None
# 推荐
def process(x):
"""处理输入值,返回平方或None"""
return x**2 if x > 0 else None
7. 函数高级特性与最佳实践
7.1 函数作为一等公民
在Python中,函数是一等公民,这意味着:
- 可以赋值给变量
- 可以作为参数传递
- 可以作为返回值
- 可以存储在数据结构中
示例:
python复制def greet(name):
return f"Hello, {name}!"
def goodbye(name):
return f"Goodbye, {name}!"
def get_greeting(kind):
if kind == "hello":
return greet
else:
return goodbye
func = get_greeting("hello")
print(func("Alice")) # Hello, Alice!
7.2 闭包
闭包是引用了外部变量的函数,即使外部函数已经执行完毕:
python复制def make_multiplier(factor):
def multiplier(x):
return x * factor
return multiplier
double = make_multiplier(2)
print(double(5)) # 10
闭包的应用:
- 装饰器
- 回调函数
- 保持状态
- 函数工厂
7.3 装饰器基础
装饰器是修改其他函数行为的函数:
python复制def log_time(func):
def wrapper(*args, **kwargs):
import time
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end-start:.4f} seconds")
return result
return wrapper
@log_time
def slow_function():
import time
time.sleep(1)
slow_function() # 输出: slow_function took 1.0001 seconds
7.4 函数注解
Python 3支持函数注解,用于添加元数据:
python复制def greet(name: str, times: int = 1) -> str:
"""返回多次问候语
Args:
name: 要问候的人名
times: 重复次数
Returns:
拼接后的问候字符串
"""
return " ".join([f"Hello, {name}!"] * times)
注解的特点:
- 不影响函数行为
- 存储在
__annotations__属性中 - 主要用于文档和静态类型检查
7.5 函数式编程工具
Python提供了一些函数式编程工具:
7.5.1 map
python复制numbers = [1, 2, 3, 4]
squared = list(map(lambda x: x**2, numbers))
print(squared) # [1, 4, 9, 16]
7.5.2 filter
python复制numbers = [1, 2, 3, 4, 5, 6]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [2, 4, 6]
7.5.3 reduce
python复制from functools import reduce
numbers = [1, 2, 3, 4]
product = reduce(lambda x, y: x * y, numbers)
print(product) # 24
7.6 函数设计最佳实践
- 单一职责原则:一个函数只做一件事
- 短小精悍:理想情况下不超过20行
- 描述性命名:函数名应清晰表达其目的
- 避免副作用:除非必要,不要修改外部状态
- 合理使用注释:解释为什么,而不是做什么
- 适当分解:复杂逻辑拆分为多个小函数
- 参数数量控制:最好不超过5个
- 错误处理:在适当层级处理错误
8. 常见问题与解决方案
8.1 函数参数传递是值传递还是引用传递?
Python采用"对象引用传递"方式:
- 不可变对象(数字、字符串、元组)表现为值传递
- 可变对象(列表、字典)表现为引用传递
示例:
python复制def modify(x, y):
x = 2 # 不影响外部
y[0] = "modified" # 会影响外部
a = 1
b = ["original"]
modify(a, b)
print(a) # 1 (未改变)
print(b) # ['modified'] (已改变)
8.2 如何实现函数重载?
Python不支持传统意义上的函数重载,但有替代方案:
- 使用默认参数
- 使用可变参数(*args, **kwargs)
- 使用functools.singledispatch
python复制from functools import singledispatch
@singledispatch
def process(data):
raise NotImplementedError("未支持的类型")
@process.register(str)
def _(data):
print(f"处理字符串: {data}")
@process.register(int)
def _(data):
print(f"处理整数: {data}")
process("hello") # 处理字符串: hello
process(42) # 处理整数: 42
8.3 如何记忆函数结果?
对于计算昂贵的函数,可以使用缓存:
python复制from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(50)) # 快速计算
8.4 如何处理函数中的异常?
良好的错误处理应该:
- 只在适当层级捕获异常
- 提供有意义的错误信息
- 避免捕获所有异常
- 清理资源(使用finally或上下文管理器)
示例:
python复制def divide(a, b):
try:
return a / b
except ZeroDivisionError as e:
print(f"错误: {e}")
return None
except TypeError as e:
print(f"类型错误: {e}")
return None
8.5 如何测试函数?
使用unittest或pytest编写测试:
python复制# test_math.py
import unittest
def add(a, b):
return a + b
class TestMath(unittest.TestCase):
def test_add(self):
self.assertEqual(add(2, 3), 5)
self.assertEqual(add(-1, 1), 0)
self.assertEqual(add(0, 0), 0)
if __name__ == "__main__":
unittest.main()
9. 实战案例:构建一个简单的计算器
让我们综合运用所学知识,构建一个命令行计算器。
9.1 设计思路
- 支持加、减、乘、除运算
- 提供历史记录功能
- 良好的错误处理
- 可扩展的架构
9.2 实现代码
python复制import math
from typing import List, Tuple, Optional
def add(a: float, b: float) -> float:
"""加法运算"""
return a + b
def subtract(a: float, b: float) -> float:
"""减法运算"""
return a - b
def multiply(a: float, b: float) -> float:
"""乘法运算"""
return a * b
def divide(a: float, b: float) -> Optional[float]:
"""除法运算"""
try:
return a / b
except ZeroDivisionError:
print("错误: 除数不能为零")
return None
def calculator(operation: str, a: float, b: float) -> Optional[float]:
"""计算器核心函数
Args:
operation: 操作类型 ('add', 'subtract', 'multiply', 'divide')
a: 第一个操作数
b: 第二个操作数
Returns:
计算结果或None(如果出错)
"""
operations = {
'add': add,
'subtract': subtract,
'multiply': multiply,
'divide': divide
}
if operation not in operations:
print(f"错误: 不支持的操作 '{operation}'")
return None
return operations[operation](a, b)
def main():
"""主交互循环"""
history: List[Tuple[str, float, float, Optional[float]]] = []
while True:
print("\n可用操作: add, subtract, multiply, divide, history, exit")
command = input("请输入命令: ").strip().lower()
if command == 'exit':
break
if command == 'history':
for i, (op, a, b, result) in enumerate(history, 1):
print(f"{i}. {a} {op} {b} = {result}")
continue
if command not in ('add', 'subtract', 'multiply', 'divide'):
print("错误: 无效命令")
continue
try:
a = float(input("输入第一个数字: "))
b = float(input("输入第二个数字: "))
except ValueError:
print("错误: 请输入有效数字")
continue
result = calculator(command, a, b)
if result is not None:
print(f"结果: {result}")
history.append((command, a, b, result))
if __name__ == "__main__":
main()
9.3 代码解析
- 函数分解:每个运算有独立函数,遵循单一职责原则
- 类型注解:使用typing模块提高代码可读性
- 错误处理:对除零和无效输入进行处理
- 历史记录:使用列表存储计算历史
- 可扩展性:可以轻松添加新运算(如幂运算)
9.4 改进方向
- 添加更多运算(如幂、平方根)
- 实现撤销功能
- 添加单元测试
- 支持表达式计算(如"3 + 4 * 2")
- 添加图形界面
10. 函数性能优化技巧
10.1 避免不必要的计算
python复制# 不推荐
def calculate(values):
result = sum(values) / len(values)
print(f"平均值: {result}")
print(f"总和: {sum(values)}") # 重复计算sum
# 推荐
def calculate(values):
total = sum(values)
avg = total / len(values)
print(f"平均值: {avg}")
print(f"总和: {total}")
10.2 使用生成器处理大数据
python复制# 不推荐
def process_all(data):
results = []
for item in data:
results.append(complex_calculation(item))
return results
# 推荐
def process_stream(data):
for item in data:
yield complex_calculation(item)
10.3 局部变量访问更快
python复制import math
def calculate(values):
local_sqrt = math.sqrt # 局部变量访问更快
return [local_sqrt(x) for x in values]
10.4 使用functools.partial
python复制from functools import partial
def power(base, exponent):
return base ** exponent
square = partial(power, exponent=2)
cube = partial(power, exponent=3)
print(square(5)) # 25
print(cube(3)) # 27
10.5 避免频繁的函数调用
对于性能关键的代码,有时需要减少函数调用:
python复制# 在循环内调用函数
result = []
for x in big_list:
result.append(process(x))
# 改为先处理再循环
processed = process_all(big_list) # 一次处理
11. Python函数与其他语言的比较
11.1 与C/C++函数比较
-
参数传递:
- Python:对象引用传递
- C/C++:值传递、引用传递、指针传递
-
返回值:
- Python:可返回多个值(元组)
- C/C++:只能返回一个值
-
函数重载:
- Python:不支持传统重载
- C++:支持函数重载
-
默认参数:
- Python:默认参数在定义时计算
- C++:默认参数在调用时计算
11.2 与Java函数比较
-
方法定义:
- Python:使用def
- Java:需要指定返回类型和访问修饰符
-
多返回值:
- Python:支持
- Java:不支持(需要使用对象或数组)
-
Lambda表达式:
- Python:更简洁灵活
- Java:需要函数式接口
-
异常处理:
- Python:使用try-except
- Java:使用try-catch,需要声明抛出异常
11.3 与JavaScript函数比较
-
定义方式:
- Python:def、lambda
- JavaScript:function、箭头函数
-
提升(Hoisting):
- Python:无提升
- JavaScript:函数声明会提升
-
this绑定:
- Python:显式self参数
- JavaScript:动态this绑定
-
闭包:
- 两者都支持闭包
- JavaScript的闭包更常用于模块模式
12. 函数调试技巧
12.1 使用print调试
最简单的调试方法:
python复制def complex_function(a, b):
print(f"输入参数: a={a}, b={b}") # 调试输出
result = a * b
print(f"中间结果: {result}") # 调试输出
result += 100
return result
12.2 使用logging模块
更专业的调试方式:
python复制import logging
logging.basicConfig(level=logging.DEBUG)
def complex_function(a, b):
logging.debug(f"输入参数: a={a}, b={b}")
result = a * b
logging.debug(f"中间结果: {result}")
result += 100
return result
12.3 使用pdb调试器
交互式调试:
python复制import pdb
def buggy_function(x):
pdb.set_trace() # 设置断点
result = x * 2
return result + 1
常用pdb命令:
- n(ext):执行下一行
- s(tep):进入函数
- c(ontinue):继续执行
- p:打印变量
- l(ist):显示代码
- q(uit):退出
12.4 使用IDE调试功能
现代IDE(如PyCharm、VSCode)提供:
- 图形化断点
- 变量监视
- 调用栈查看
- 条件断点
- 交互式控制台
13. 函数文档与注释
良好的文档是代码可维护性的关键。
13.1 文档字符串(Docstring)
遵循PEP 257规范:
python复制def calculate(a, b):
"""计算两个数的和与积
这是一个多行文档字符串示例,第一行是简要描述,
空一行后是详细描述。
Args:
a (int): 第一个操作数
b (int): 第二个操作数
Returns:
tuple: 包含 (和, 积) 的元组
Raises:
TypeError: 如果参数不是整数
Examples:
>>> calculate(2, 3)
(5, 6)
"""
if not isinstance(a, int) or not isinstance(b, int):
raise TypeError("参数必须是整数")
return a + b, a * b
13.2 类型注解
Python 3.5+支持类型注解:
python复制from typing import Tuple, Union
def calculate(
a: int,
b: int
) -> Tuple[int, int]:
"""计算两个数的和与积"""
return a + b, a * b
13.3 注释原则
- 解释为什么,而不是做什么
- 避免显而易见的注释
- 保持注释与代码同步
- 使用TODO标记待办事项
- 注释复杂的算法或业务逻辑
python复制# 不推荐
x = x + 1 # 给x加1
# 推荐
# 调整计数器以跳过标题行
x = x + 1
14. 函数测试与验证
14.1 单元测试基础
使用unittest模块:
python复制import unittest
def add(a, b):
return a + b
class TestAdd(unittest.TestCase):
def test_add_positive(self):
self.assertEqual(add(2, 3), 5)
def test_add_negative(self):
self.assertEqual(add(-1, -1), -2)
def test_add_zero(self):
self.assertEqual(add(0, 0), 0)
if __name__ == "__main__":
unittest.main()
14.2 使用pytest
更简洁的测试框架:
python复制# test_math.py
def add(a, b):
return a + b
def test_add():
assert add(2, 3) == 5
assert add(-1, -1) == -2
assert add(0, 0) == 0
运行测试:
bash复制pytest test_math.py
14.3 测试覆盖率
使用pytest-cov检查覆盖率:
bash复制pytest --cov=my_module tests/
14.4 参数化测试
测试多组输入:
python复制import pytest
@pytest.mark.parametrize("a,b,expected", [
(2, 3, 5),
(-1, -1, -2),
(0, 0, 0),
(1.5, 2.5, 4.0)
])
def test_add(a, b, expected):
assert add(a, b) == expected
15. 函数在项目中的实际应用
15.1 Web开发中的视图函数
Flask示例:
python复制from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return "欢迎来到首页"
@app.route("/user/<username>")
def show_user(username):
return f"用户: {username}"
15.2 数据处理管道
python复制def process_data_pipeline(data):
data = clean_data(data)
data = transform_data(data)
results = analyze_data(data)
return generate_report(results)
15.3 自动化脚本
python复制def backup_files(source_dir, dest_dir):
if not validate_paths(source_dir, dest_dir):
raise ValueError("无效的路径")
files = list_files(source_dir)
copied = copy_files(files, dest_dir)
log_results(copied)
send_notification(f"备份完成: {len(copied)}个文件")
15.4 算法实现
快速排序实现:
python复制def quicksort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quicksort(left) + middle + quicksort(right)
16. 函数设计模式
16.1 工厂模式
python复制def create_operator(op):
if op == "+":
return lambda a, b: a + b
elif op == "-":
return lambda a, b: a - b
elif op == "*":
return lambda a, b: a * b
elif op == "/":
return lambda a, b: a / b
else:
raise ValueError(f"未知运算符: {op}")
adder = create_operator("+")
print(adder(2, 3)) # 5
16.2 策略模式
python复制def execute_payment(amount, strategy):
return strategy(amount)
def credit_card_payment(amount):
print(f"处理信用卡支付: {amount}")
return True
def paypal_payment(amount):
print(f"处理PayPal支付: {amount}")
return True
execute_payment(100, credit_card_payment)
execute_payment(50, paypal_payment)
16.3 装饰器模式
python复制def retry(max_attempts=3):
def decorator(func):
def wrapper(*args, **kwargs):
attempts = 0
while attempts < max_attempts:
try:
return func(*args, **kwargs)
except Exception as e:
attempts += 1
print(f"尝试 {attempts} 失败: {e}")
raise Exception(f"超过最大重试次数 {max_attempts}")
return wrapper
return decorator
@retry(max_attempts=2)
def unreliable_function():
import random
if random.random() < 0.7:
raise ValueError("随机失败")
return "成功"
16.4 观察者模式
python复制def create_observable():
observers = []
def register(observer):
observers.append(observer)
def notify(*args, **kwargs):
for observer in observers:
observer(*args, **kwargs)
return register, notify
register, notify = create_observable()
def logger(message):
print(f"日志: {message}")
def alert(message):
print(f"警报: {message}")
register(logger)
register(alert)
notify("系统启动")
17. 函数性能分析
17.1 使用timeit
python复制import timeit
def test_func():
return sum(range(10000))
time = timeit.timeit(test_func, number=1000)
print(f"平均时间: {time/1000:.6f}秒")
17.2 使用cProfile
python复制import cProfile
def slow_function():
total = 0
for i in range(10000):
for j in range(10000):
total += i * j
return total
cProfile.run('slow_function()', sort='cumulative')
17.3 性能优化示例
优化前:
python复制def sum_of_squares(numbers):
result = 0
