
01
引言
在日常工作中,当大家的项目规模越来越大时,高效管理计算资源就成为了必然要求。遗憾的是,Python,尤其是与 C 或 C++等编程语言相比,内存效率似乎不高。但是从优秀的模块设计到先进的数据结构和算法,有很多方法可以显著优化 Python 程序的内存利用效率。
本文重点介绍三种有效的内存优化技巧,掌握这些技巧将大大提高大家的 Python 编程技能。闲话少说,我们直接开始吧!
02
类的定义中使用__slots__
class Author:def __init__(self, name, age):self.name = nameself.age = ageme = Author('AI Way', 30)me.job = 'Software Engineer'print(me.job)# Software Engineer
class Author:__slots__ = ('name', 'age')def __init__(self, name, age):self.name = nameself.age = ageme = Author('AI Way', 30)me.job = 'Software Engineer'print(me.job)# AttributeError: 'Author' object has no attribute 'job'
03
验证__slots__作用
import sysclass Author:def __init__(self, name, age):self.name = nameself.age = ageclass AuthorWithSlots:__slots__ = ['name', 'age']def __init__(self, name, age):self.name = nameself.age = age
# Creating instancesme = Author('AI Way', 30)me_with_slots = AuthorWithSlots('AI Way', 30)
# Comparing memory usagememory_without_slots = sys.getsizeof(me) + sys.getsizeof(me.__dict__)# __slots__ classes don't have __dict__memory_with_slots = sys.getsizeof(me_with_slots)print(memory_without_slots, memory_with_slots)# 152 48print(me.__dict__)# {'name': 'AI Way', 'age': 30}print(me_with_slots.__dict__)# AttributeError: 'AuthorWithSlots' object has no attribute '__dict__'
如上面的代码的输出所示,由于使用了__slots__,实例me_with_slots 没有__dict__字典。与需要保存额外字典的 me 实例相比,它有效地节省了内存资源开销。
04
使用生成器
生成器是 Python 中列表的懒启动版本。它们的工作方式类似于元素生成工厂:只要调用 next() 方法,就会生成一个元素,而不是一次性计算所有元素。因此,在处理大型数据集时,它们的内存效率非常高。
def number_generator():for i in range(100):yield inumbers = number_generator()print(numbers)# <generator object number_generator at 0x104a57e40>print(next(numbers))# 0print(next(numbers))# 1
上面的代码展示了一个编写和使用生成器的基本示例。关键字yield是生成器定义的核心。使用它意味着只有在调用next()方法时,才会产生第i个元素。
接着,让我们不妨来对比一下生成器和列表,看看哪个更节省内存:
import sysnumbers = []for i in range(100):numbers.append(i)def number_generator():for i in range(100):yield inumbers_generator = number_generator()print(sys.getsizeof(numbers_generator))# 112print(sys.getsizeof(numbers))# 920
上述程序的结果证明,使用生成器可以大大节省内存使用量。
顺便说一下,如果我们把列表生成式中的方括号转换成小括号,它就会变成一个生成器表达式。这是在 Python 中定义生成器的一种更简单的方法:
import sysnumbers = [i for i in range(100)]numbers_generator = (i for i in range(100))print(sys.getsizeof(numbers_generator))# 112print(sys.getsizeof(numbers))# 920
05
谨慎选择数据类型
资深的 Python开发人员会谨慎而精确地选择数据类型。因为在某些情况下,使用一种数据类型比使用另一种数据类型更节省内存。
元组比列表更节省内存
由于元组是不可变的(创建后不能更改),因此 Python 可以对内存分配进行优化。然而,列表是可变的,因此需要额外的空间来容纳可能的修改。
import sysmy_tuple = (1, 2, 3, 4, 5)my_list = [1, 2, 3, 4, 5]print(sys.getsizeof(my_tuple))# 80print(sys.getsizeof(my_list))# 120
如上面的代码段所示,即使包含相同的元素,元组my_tuple使用的内存也比 列表list 少。因此,如果在创建后不需要更改数据,我们应该选择元组而不是列表。
数组比列表更节省内存
Python中的数组array要求元素具有相同的数据类型(例如,所有整数或所有浮点数),但列表可以存储不同类型的对象,这就不可避免地需要更多内存。因此,如果列表中的元素类型相同,使用数组会更节省内存。
import sysimport arraymy_list = [i for i in range(1000)]my_array = array.array('i', [i for i in range(1000)])print(sys.getsizeof(my_list))# 8856print(sys.getsizeof(my_array))# 4064
06
本文重点介绍了三种常用的可以在编写代码的过程中优化内存的技巧,主要包括在类定义中使用 slots,使用生成器以及谨慎选择数据类型。学会这些技巧,可以极大提升大家的编码水平。
您学废了嘛?
点击上方小卡片关注我
扫码进群,交个朋友!


