本文将探讨不同Python版本中各种数据类型的内存大小。此外,我们将学习如何确定对象的内存大小及其内置数据类型。那么,让我们深入了解一下吧!
什么是变量?
变量是一个命名的内存块,这意味着它是可以使用预定名称访问的内存部分。在低级编程语言中,变量必须定义其数据类型,因为不同的数据类型需要不同的内存量。然而,Python是一种解释性语言,因此我们在显式声明变量时不需要指定变量的数据类型。
什么是数据类型?
数据类型是对变量的约束。它指定它包含的值的域。因此,例如,数据类型为浮点型的变量将包含十进制值。数据类型为 int 的变量将包含整数值。数据类型为 char 的变量将仅包含一个字符。每个变量都有一个数据类型。在Python中,我们不必在声明时指定数据类型。Python 自行解释变量的数据类型。
每种数据类型仅占用固定的内存大小。但特定数据类型占用的内存大小因每种数据类型而异。甚至每种语言的情况也有所不同。它还取决于您使用的系统。在Python中,它还取决于您使用的Python的实现。
在本文中,我们将重点讨论最常用的 Python 实现(即 CPython)中变量的内存大小。我们不会考虑 Python 的不同实现,例如 IronPython 或 Jython。
相关:了解有关Python 中数据类型的更多信息。
如何在Python中检查变量的内存大小?
getsizeof()
为了在 Python 中检查变量的内存大小,我们在 Python 的 sys 库中调用了一个函数。这个 getsizeof 函数为我们提供了特定变量消耗的内存空间的字节数。使用它很简单。
让我们使用 getsizeof 函数检查不同数据类型的变量的大小。
整数变量
1
2
3
|
import sys integer = 10 print ( "The size of the integer variable is:" ,sys.getsizeof(integer), "bytes." ) |
输出The size of the integer variable is: 28 bytes.
在上面的代码块中,首先,我们导入了 sys 库。该 sys 库具有getsizeof()
我们将用来获取变量大小的函数。然后我们创建了一个整型变量并将其初始化为 10。
因此,整型变量的大小为 28 字节。请注意,此大小在每个系统上可能有所不同。但如果你熟悉C语言,C语言中整型变量的大小是4个字节。为什么差别这么大?28 是该特定系统上整个对象消耗的内存大小。
一般来说,Python中的整型变量在32位系统上消耗4字节的内存空间,在64位系统上消耗8字节的内存空间。
浮点变量
1
2
3
|
import sys decimal = 10.01 print ( "The size of float variable is:" ,sys.getsizeof(decimal), "bytes." ) |
输出The size of the integer variable is: 24 bytes.
所以Python中的浮点值总共占用24字节的内存空间。无论值有多大,浮点值都会占用相同的空间,而较大的整数比较小的整数会占用更多的空间。
字符串变量
什么是字符串?
与许多低级语言一样,Python 中没有 char 数据类型。在 Python 中,我们有字符串变量。字符串是字符数组。它是派生数据类型。测量字符串的内存消耗可能很棘手。让我们检查一下该字符串数据类型消耗的空间。
首先,让我们检查一个空字符串占用了多少空间。
空字符串
string = "" print ( "The size of the empty string is:" ,sys.getsizeof(string), "bytes." ) |
输出The size of the empty string is: 49 bytes.
因此,一个空字符串占用 49 个字节的内存空间。Python 中单个字符占用的空间之大真是不可思议。
单个字符
string = "a" print ( "The size of a single is:" ,sys.getsizeof(string), "bytes." ) |
输出The size of a single character is: 50 bytes.
所以Python中单个字符的大小是50字节。C中单个字符占用1个字节的内存空间。因此,在Python中存储单个字符比在C中存储单个字符需要多50倍的空间。与空字符串相比,单个字符仅额外占用1个字节的内存空间。
在我们得出任何结论之前,让我们检查一下 2 个字符的字符串占用了多少空间。
两个字符的字符串
1
2
|
string = "ab" print ( "The size of a string of two characters is:" ,sys.getsizeof(string), "bytes." ) |
输出The size of a string of two characters is: 51 bytes.
好吧,两个字符的字符串占用了 51 个字节的内存空间。所以这意味着一个空字符串占用 49 个字节的内存空间,并且对于每个字符,需要 1 个额外的字节。
为什么空字符串会占用这么多空间?
字符串是Python中的一个对象。它是一个字符数组。Python 为字符串提供了很多功能。为此,Python 占据了所有这些空间。Python 确实需要大量空间来存储字符串,但与此同时,Python 提供的灵活性对于运行时间来说是一个很好的权衡。
现在我们已经检查了所有这些基本数据类型的内存消耗,让我们检查一下列表、元组、字典等的内存消耗。
List消耗的内存空间
1
2
3
4
5
6
|
import sys list_ = [] print ( "The size of the empty list is:" ,sys.getsizeof(list_), "bytes." ) for i in range ( 10 ): list_.append( 0 ) print ( "The size of the empty list is:" ,sys.getsizeof(list_), "bytes." ) |
在上面的代码中,首先,我们检查了空列表的大小。空列表占用 56 字节的空间。一旦我们添加一个元素,列表的大小就会增加 32 个字节。然后大小保持不变,直到添加 4 个元素。对于第 5 个元素,它再次将大小增加 32 字节。所以列表占用了56字节的开销。那是很大的空间。这意味着我们每次创建列表时,都会额外占用 56 字节的内存空间。
请注意,列表中每个元素的内存使用量仅为 8 个字节,无论该元素占用多少空间。这是因为列表不存储元素;而是存储元素。它存储指向元素的指针。
相关:深入学习Python 中的列表。
Tuple消耗的内存空间
1
2
3
4
5
6
7
8
9
|
import sys tuple_ = () print ( "The size of the empty tuple is:" ,sys.getsizeof(tuple_), "bytes." ) tuple_ = ( 0 ,) print ( "The size of the tuple with 1 element is:" ,sys.getsizeof(tuple_), "bytes." ) tuple_ = ( 0 , 0 ,) print ( "The size of the tuple with 2 elements is:" ,sys.getsizeof(tuple_), "bytes." ) tuple_ = ( 0 , 0 , 0 ,) print ( "The size of the tuple with 3 element is:" ,sys.getsizeof(tuple_), "bytes." ) |
在上面的代码中,首先,我们检查了空元组的大小。一个空元组占用 40 字节的空间。然后我们添加了一个元素。元组的大小增加了 8 个字节。然后,对于每个元素,我们将元组的大小增加 8。同样,对于元组中的每个元素,无论元素占用多少空间,内存使用量都将仅为 8 个字节。这是因为元组不存储元素;它存储指向元素的指针。
Set消耗的内存空间
1
2
3
4
5
6
|
import sys set_ = set () print ( "The size of the empty set is:" ,sys.getsizeof(set_), "bytes." ) for i in range ( 10 ): set_.add(i) print (f "The size of the set with {i+1} element is:" ,sys.getsizeof(set_), "bytes." ) |
该集的内存开销为 216 字节。然后当集合填满时每次添加 512 字节。该集合速度快但消耗大量内存空间。
字典消耗的内存空间
1
2
3
4
5
6
|
import sys dict_ = dict () print ( "The size of the empty dictionary is:" ,sys.getsizeof(dict_), "bytes." ) for i in range ( 10 ): dict_[i] = i print (f "The size of the set with {i+1} element is:" ,sys.getsizeof(dict_), "bytes." ) |
该集的内存开销为 232 字节。然后当集合填满时每次添加 128 个字节。该集合速度快但消耗大量内存空间。
深度获取大小
检查对象或数据结构(如列表、元组或集合)的总内存使用情况可能很棘手,因为它可能具有未添加到 getsizeof 函数中的列表、元组或嵌套对象。要检查对象的总内存使用量,我们使用 deep_getsizeof 方法。在此方法中,我们对对象的每个部分递归调用 getsizeof 函数。让我们看看这个函数是如何运行的。
1
2
3
4
5
6
7
8
9
10
11
|
import sys def deepgso(ob): size = sys.getsizeof(ob) if isinstance (ob, ( list , tuple , set )): for element in ob: size + = deepgso(element) if isinstance (ob, dict ): for k,v in ob.items(): size + = deepgso(k) size + = deepgso(v) return size |
首先,我们声明该函数。在函数中,我们创建一个变量大小。我们根据 getsizeof 函数添加对象的大小。然后,对于对象中的每个元素,我们对其运行 getsizeof 函数。每个元素的大小都会添加到 size 变量中。最后,我们返回 size 变量,它存储对象的总大小。
我们来测试一下这个功能。
list_ = [[ 1 ], 1 , "1" ] print ( "Space consumed by the list using getsizeof:" ,sys.getsizeof(list_)) print ( "Total space consumed by the list:" ,deepgso(list_)) |
输出Space consumed by the list using getsizeof: 80
Total space consumed by the list: 250
我们获取了一个列表,其中包含一个元素、一个整数和一个包含单个字符的字符串。使用 getsizeof 函数,我们得到的大小为 80 字节。56 作为开销,每个元素 8。我们知道这只是列表所消耗的空间。不包括列表内的元素。因此,为了将元素也包含在列表中,我们使用了我们创建的 deep_getsizeof 函数。使用它,我们得到 250 字节的总空间。
Python 中的内存泄漏
内存泄漏是 Python 和所有编程语言中的一个大问题。但在Python中这个问题很严重,因为Python中的变量占用了太多的空间。为了避免Python中的内存泄漏,我们使用了一个名为tracemalloc的内置模块。Tracemalloc可以用来检查程序的内存消耗情况,并采取措施防止内存泄漏。要检查程序的内存消耗情况,我们可以使用 get_traced_memory 函数。它返回两个值,程序的当前内存消耗和程序的峰值内存消耗。
为了避免内存泄漏,我们可以在程序的开头使用tracemalloc的start函数,然后在程序的末尾使用tracemalloc的stop函数。这将释放程序中每次使用的所有内存。
结论
Python中的变量占用太多空间。Python 无疑是一门很棒的语言。Python 提供的功能之多是任何其他语言所无法提供的。但是Python的内存消耗非常高。这使得 Python 在内存有限的地方成为一个糟糕的选择。我们还需要确保我们的程序中没有内存泄漏。永远记住释放程序占用的空间。
参考
堆栈溢出对同一问题的回答。