提升Python代码性能的五个技巧:__slots__内存优化、列表推导式、@lru_cache缓存、生成器以及局部变量优化。
原文标题:Python高性能编程:五种核心优化技术的原理与Python代码
原文作者:数据派THU
冷月清谈:
1. __slots__机制:通过限制实例属性,减少内存开销,提升属性访问速度。实验证明,使用__slots__可以显著降低内存占用,并加快实例创建速度。
2. 列表推导式:利用列表推导式替代传统的for循环,能够更简洁地表达代码逻辑,并且通常比传统循环快 30-50%。 这得益于列表推导式底层更高效的C语言实现。
3. @lru_cache装饰器:对于需要重复执行相同计算的场景,使用@lru_cache装饰器缓存函数调用结果,可以避免重复计算,显著提高性能。尤其适用于递归函数或具有重复计算特征的任务。
4. 生成器:利用生成器动态生成数据,避免一次性将所有数据加载到内存,从而降低内存占用。这对于处理大规模数据集和流式数据非常有效,例如处理大型日志文件时,逐行读取和处理可以有效控制内存使用。
5. 局部变量优化:优先使用局部变量,可以减少变量查找时间,提高代码执行效率。因为访问局部变量比访问全局变量更快,实验证明,局部变量的访问速度可以显著提升。
怜星夜思:
2、除了文章提到的几种方法外,大家在实际项目中还用过哪些 Python 性能优化技巧?
3、文章中的例子主要集中在计算密集型任务上。对于 I/O 密集型任务,有哪些 Python 性能优化策略?
原文内容
1、__slots__机制:内存优化
from pympler import asizeof
class person:
def init(self, name, age):
self.name = name
self.age = age
unoptimized_instance = person(“Harry”, 20)
print(f"UnOptimized memory instance: {asizeof.asizeof(unoptimized_instance)} bytes")

from pympler import asizeof
class person:
def init(self, name, age):
self.name = name
self.age = ageunoptimized_instance = person(“Harry”, 20)
print(f"UnOptimized memory instance: {asizeof.asizeof(unoptimized_instance)} bytes")class Slotted_person:
slots = [‘name’, ‘age’]
def init(self, name, age):
self.name = name
self.age = age
optimized_instance = Slotted_person(“Harry”, 20)
print(f"Optimized memory instance: {asizeof.asizeof(optimized_instance)} bytes")

import time import gc # 垃圾回收机制 from pympler import asizeof
class Person:
def init(self, name, age):
self.name = name
self.age = ageclass SlottedPerson:
slots = [‘name’, ‘age’]
def init(self, name, age):
self.name = name
self.age = age性能测量函数
def measure_time_and_memory(cls, name, age, iterations=1000):
gc.collect() # 强制执行垃圾回收
start_time = time.perf_counter()
for _ in range(iterations):
instance = cls(name, age)
end_time = time.perf_counter()
memory_usage = asizeof.asizeof(instance)
avg_time = (end_time - start_time) / iterations
return memory_usage, avg_time * 1000 # 转换为毫秒测量未优化类的性能指标
unoptimized_memory, unoptimized_time = measure_time_and_memory(Person, “Harry”, 20)
print(f"Unoptimized memory instance: {unoptimized_memory} bytes")
print(f"Time taken to create unoptimized instance: {unoptimized_time:.6f} milliseconds")测量优化类的性能指标
optimized_memory, optimized_time = measure_time_and_memory(SlottedPerson, “Harry”, 20)
print(f"Optimized memory instance: {optimized_memory} bytes")
print(f"Time taken to create optimized instance: {optimized_time:.6f} milliseconds")计算性能提升比率
speedup = unoptimized_time / optimized_time
print(f"{speedup:.2f} times faster")
2、 列表推导式:优化循环操作
import time
使用传统for循环的实现
start = time.perf_counter()
squares_loop =for i in range(1, 10_000_001):
squares_loop.append(i ** 2)
end = time.perf_counter()print(f"For loop: {end - start:.6f} seconds")
使用列表推导式的实现
start = time.perf_counter()
squares_comprehension = [i ** 2 for i in range(1, 10_000_001)]
end = time.perf_counter()print(f"List comprehension: {end - start:.6f} seconds")
-
适用场景:对现有可迭代对象进行转换和筛选操作,特别是需要生成新列表的场景。
-
不适用场景:涉及复杂的多重嵌套循环或可能降低代码可读性的复杂操作。
3、@lru_cache装饰器:结果缓存优化
import time
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)start = time.perf_counter()
print(f"Result: {fibonacci(35)}“)
print(f"Time taken without cache: {time.perf_counter() - start:.6f} seconds”)

from functools import lru_cache import time
@lru_cache(maxsize=128) # 设置缓存容量为128个结果
def fibonacci_cached(n):
if n <= 1:
return n
return fibonacci_cached(n - 1) + fibonacci_cached(n - 2)start = time.perf_counter()
print(f"Result: {fibonacci_cached(35)}“)
print(f"Time taken with cache: {time.perf_counter() - start:.6f} seconds”)

Without cache: 3.456789 seconds With cache: 0.000234 seconds
Speedup factor = Without cache time / With cache time
Speedup factor = 3.456789 seconds / 0.000234 seconds
Speedup factor ≈ 14769.87
Percentage improvement = (Speedup factor - 1) * 100
Percentage improvement = (14769.87 - 1) * 100
Percentage improvement ≈ 1476887%
-
maxsize:用于限制缓存结果的数量,默认值为128。设置为None时表示不限制缓存大小。
-
lru_cache(None):适用于长期运行且内存充足的应用场景。
-
具有固定输入产生固定输出特征的函数,如递归计算或特定的API调用。
-
计算开销显著大于内存存储开销的场景。
4、生成器:内存效率优化
import sys
使用列表存储大规模数据
big_data_list = [i for i in range(10_000_000)]
分析内存占用
print(f"Memory usage for list: {sys.getsizeof(big_data_list)} bytes")
数据处理
result = sum(big_```python
result = sum(big_data_list)
print(f"Sum of list: {result}")
Memory usage for list: 89095160 bytes
Sum of list: 49999995000000
使用生成器处理数据:使用生成器处理大规模数据
big_data_generator = (i for i in range(10_000_000))
分析内存占用
print(f"Memory usage for generator: {sys.getsizeof(big_data_generator)} bytes")
数据处理
result = sum(big_data_generator)
print(f"Sum of generator: {result}")
实验结果分析:
Memory saved = 89095160 bytes - 192 bytes
Memory saved = 89094968 bytes
Percentage saved = (Memory saved / List memory usage) * 100
Percentage saved = (89094968 bytes / 89095160 bytes) * 100
Percentage saved ≈ 99.9998%
-
文件读取采用逐行处理方式,避免一次性加载整个文件
-
使用生成器表达式进行计数,确保内存使用效率
-
代码结构清晰,易于维护和扩展
5、局部变量优化:提升变量访问效率
-
局部变量:直接在函数的本地命名空间中查找,访问速度快
-
全局变量:需要先在本地命名空间查找,未找到后再在全局命名空间查找,增加了查找开销
import time
定义全局变量
global_var = 10
访问全局变量的函数
def access_global():
global global_var
return global_var访问局部变量的函数
def access_local():
local_var = 10
return local_var测试全局变量访问性能
start_time = time.time()
for _ in range(1_000_000):
access_global() # 全局变量访问
end_time = time.time()
global_access_time = end_time - start_time测试局部变量访问性能
start_time = time.time()
for _ in range(1_000_000):
access_local() # 局部变量访问
end_time = time.time()
local_access_time = end_time - start_time性能分析
print(f"Time taken to access global variable: {global_access_time:.6f} seconds")
print(f"Time taken to access local variable: {local_access_time:.6f} seconds")
实验结果:
Time taken to access global variable: 0.265412 seconds
Time taken to access local variable: 0.138774 seconds
Speedup factor = 0.265412 seconds / 0.138774 seconds ≈ 1.91
Performance improvement ≈ 91.25%
性能优化实践总结
-
内存效率优化
-
使用__slots__限制实例属性
-
采用生成器处理大规模数据
-
合理使用局部变量
-
计算效率优化
-
使用列表推导式替代传统循环
-
通过lru_cache实现结果缓存
-
优化变量访问策略
-
代码质量平衡
-
保持代码的可读性和维护性
-
针对性能瓶颈进行优化
-
避免过度优化