📜  减少Python对象大小的技巧

📅  最后修改于: 2022-05-13 01:55:00.727000             🧑  作者: Mango

减少Python对象大小的技巧

与 C 或 C++ 等编程语言相比,我们都知道Python的一个非常普遍的缺点。由于Python对象会消耗大量内存,因此速度要慢得多,并且不太适合执行内存密集型任务。在处理某些任务时,这可能会导致内存问题。当 RAM 在执行期间因任务而过载并且程序开始冻结或行为不自然时,我们将其称为内存问题。

让我们看看我们可以有效地使用此内存并减小对象大小的一些方法。

使用内置字典:

我们都非常熟悉Python中的字典数据类型。这是一种以键和值的形式存储数据的方式。但是在内存管理方面,字典并不是最好的。事实上,这是最糟糕的。让我们看一个例子:

# importing the sys library
import sys 
  
Coordinates = {'x':3, 'y':0, 'z':1}
  
print(sys.getsizeof(Coordinates))
输出:
288

我们看到数据类型字典的一个实例占用 288 个字节。因此,当我们有很多实例时,它将消耗大量内存:

因此,我们得出结论,在处理内存效率高的程序时,字典不适合。

使用元组:

元组非常适合存储不可变数据值,并且与字典相比在减少内存使用方面也非常有效:

import sys
  
Coordinates = (3, 0, 1)
  
print(sys.getsizeof(Coordinates))
输出:
72

为简单起见,我们假设索引0、1、2分别代表x、y、z 。所以从 288 字节,我们只使用元组而不是字典就可以减少到 72 字节。仍然不是很有效。如果我们有大量实例,我们仍然需要大量内存:

使用类:

通过将代码安排在类中,与使用字典和元组相比,我们可以显着减少内存消耗。

import sys
  
class Point:
  
    # defining the coordinate variables
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z
  
Coordinates = Point(3, 0, 1)
print(sys.getsizeof(Coordinates))
输出:
56

我们看到同一个程序现在需要 56 个字节,而不是之前的 72 个字节。变量 x、y 和 z 各消耗 8 个字节,而其余 32 个字节由Python的内部代码消耗。如果我们有更多的实例,我们有以下分布 -

因此我们得出结论,在节省内存方面,类比字典和元组更有优势。

旁注函数sys.getsizeof(object[, default]) 规范说:“只考虑直接归因于对象的内存消耗,而不考虑它所引用的对象的内存消耗。”

所以在你的例子中:

class Point:
  
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z
  
Coordinates = Point(3, 0, 1)

对象坐标的有效内存使用量为:
sys.getsizeof(坐标) +
sys.getsizeof(Coordinates.x) +
sys.getsizeof(Coordinates.y) +
sys.getsizeof(坐标.z) =
= 56 + 28 + 24 + 28 =
= 136

请参考 https://docs。 Python.org/3/library/sys.html。

使用记录类:

Recordclass是一个相当新的Python库。它支持记录类型,这不是Python内置的。由于recordclass是 MIT 许可的第三方模块,我们需要先在终端中输入以下内容来安装它:

pip install recordclass

让我们使用recordclass来看看它是否进一步有助于减少内存大小。

# importing the installed library
import sys
from recordclass import recordclass 
  
Point = recordclass('Point', ('x', 'y', 'z'))
  
Coordinates = Point(3, 0, 1)
print(sys.getsizeof(Coordinates))

输出:

48

所以使用recordclass进一步将一个实例所需的内存从56字节减少到48字节。如果我们有大量实例,这将是分布:

使用数据对象:

在前面的示例中,在使用recordclass时,即使是垃圾值也会被收集,从而浪费了不必要的内存。这意味着仍有优化的范围。这正是使用数据对象的原因。数据对象功能属于 recordclass 模块,其特点是它不会产生任何垃圾值。

import sys
from recordclass import make_dataclass
  
Position = make_dataclass('Position', ('x', 'y', 'z'))
Coordinates = Position(3, 0, 1)
  
print(sys.getsizeof(Coordinates))

输出:

40

最后,我们看到大小从每个实例 48 字节减少到每个实例 40 字节。因此,我们看到在内存利用率最低的情况下,数据对象是组织代码的最有效方式。