Appearance
第19章:Python 性能优化基础
19.1 代码优化
代码优化是提高Python程序性能的基础,通过优化代码结构和逻辑,可以显著提升程序的运行效率。
简化代码逻辑
- 减少条件判断:优化条件判断的顺序,将最可能发生的情况放在前面
- 避免冗余代码:移除重复的代码,使用函数或循环替代
- 简化表达式:使用更简洁的表达式,减少计算步骤
使用高效的容器和方法
选择合适的数据结构:
- 列表:适合需要频繁访问元素的场景
- 字典:适合需要快速查找的场景
- 集合:适合需要去重或集合运算的场景
使用高效的方法:
- 集合去重比列表去重更高效
- 使用生成器表达式替代列表推导式(当只需要迭代一次时)
- 使用
join()方法连接字符串,比+运算符更高效
代码优化示例
python
# 优化前:使用列表去重
def remove_duplicates_list(items):
unique_items = []
for item in items:
if item not in unique_items:
unique_items.append(item)
return unique_items
# 优化后:使用集合去重
def remove_duplicates_set(items):
return list(set(items))
# 优化前:使用+运算符连接字符串
def concatenate_strings(strings):
result = ""
for s in strings:
result += s
return result
# 优化后:使用join()方法
def concatenate_strings_optimized(strings):
return "".join(strings)19.2 循环优化
循环是程序中最常见的性能瓶颈,优化循环可以显著提高程序性能。
避免嵌套循环过多
- 减少嵌套层数:尽量将嵌套循环拆分为多个单循环
- 优化循环顺序:将内循环的范围尽可能缩小
减少循环内部的重复操作
- 预计算:将循环外部的计算结果缓存,避免在循环内部重复计算
- 减少函数调用:避免在循环内部频繁调用函数
- 使用局部变量:将频繁访问的变量存储为局部变量,提高访问速度
使用列表推导式
- 列表推导式比普通循环更高效,代码更简洁
- 适用于需要创建新列表的场景
循环优化示例
python
# 优化前:普通循环
def square_numbers(numbers):
result = []
for num in numbers:
result.append(num * num)
return result
# 优化后:列表推导式
def square_numbers_optimized(numbers):
return [num * num for num in numbers]
# 优化前:循环内部重复计算
def calculate_with_repeat(numbers):
result = []
for num in numbers:
# 重复计算sqrt(2)
result.append(num * math.sqrt(2))
return result
# 优化后:预计算
def calculate_with_precompute(numbers):
sqrt_2 = math.sqrt(2) # 预计算
result = []
for num in numbers:
result.append(num * sqrt_2)
return result19.3 内存优化
内存优化可以减少程序的内存使用,提高程序的运行效率和稳定性。
避免创建不必要的变量
- 使用生成器:生成器只在需要时生成数据,不占用额外内存
- 使用迭代器:迭代器可以逐个处理数据,避免一次性加载所有数据
- 及时释放变量:对于不再使用的变量,手动设置为
None,帮助垃圾回收
及时释放无用资源
- 关闭文件:使用
with语句或手动调用close()方法关闭文件 - 释放网络连接:及时关闭网络连接,避免资源泄露
- 清理大型对象:对于大型对象,使用后及时清理
使用合适的数据类型
- 使用内置类型:内置类型(如列表、字典)经过优化,性能更好
- 使用NumPy数组:对于数值计算,NumPy数组比Python列表更高效
- 使用压缩数据结构:对于大量重复数据,使用压缩数据结构
内存优化示例
python
# 优化前:一次性加载所有数据
def process_large_file(file_path):
with open(file_path, "r") as f:
lines = f.readlines() # 一次性加载所有行到内存
for line in lines:
process_line(line)
# 优化后:逐行处理
def process_large_file_optimized(file_path):
with open(file_path, "r") as f:
for line in f: # 逐行读取,不占用额外内存
process_line(line)
# 优化前:创建不必要的中间列表
def filter_positive_numbers(numbers):
temp = []
for num in numbers:
if num > 0:
temp.append(num)
result = []
for num in temp:
result.append(num * 2)
return result
# 优化后:直接生成结果
def filter_positive_numbers_optimized(numbers):
return [num * 2 for num in numbers if num > 0]19.4 模块与函数优化
合理使用模块和函数可以提高代码的复用性和可维护性,同时也可以优化性能。
合理使用模块
- 使用标准库:标准库经过优化,性能更好
- 使用第三方库:对于特定任务,使用专门的第三方库(如NumPy、Pandas)
- 避免重复导入:在模块顶部集中导入,避免在函数内部重复导入
函数优化
- 减少函数调用开销:对于频繁调用的小函数,可以考虑内联
- 使用缓存:对于计算密集型函数,使用缓存避免重复计算
- 优化函数参数:避免传递大型对象,使用引用传递
使用装饰器和上下文管理器
- 装饰器:使用装饰器实现横切关注点(如日志、缓存)
- 上下文管理器:使用上下文管理器管理资源(如文件、锁)
模块与函数优化示例
python
# 使用缓存装饰器
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n):
"""计算斐波那契数列"""
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
# 优化前:重复计算
print(fibonacci(30)) # 第一次计算,较慢
print(fibonacci(30)) # 再次计算,同样较慢
# 优化后:使用缓存
print(fibonacci(30)) # 第一次计算,较慢
print(fibonacci(30)) # 从缓存获取,快速
# 使用上下文管理器管理资源
class Timer:
"""计时器上下文管理器"""
def __enter__(self):
self.start = time.time()
return self
def __exit__(self, *args):
self.end = time.time()
self.duration = self.end - self.start
print(f"执行时间:{self.duration:.4f}秒")
# 使用上下文管理器
with Timer():
# 执行耗时操作
time.sleep(1)通过以上优化方法,可以显著提高Python程序的性能。在实际开发中,应该根据具体情况选择合适的优化策略,同时注意代码的可读性和可维护性。性能优化是一个持续的过程,需要不断地分析和改进代码。
