在写大型程序时候的一大挑战是如何保证最少的内存使用率。但是在Python中的内存管理是比较简单的。Python显示分配内存,使用引用计数系统管理对象,当指向某一个对象的引用数变为 0 的时候,该对象所占的内存就会被释放。理论上听起来很不错,也很简单,但是在实践中,我们需要知道一些Python内存管理的知识从而让程序在运行过程中能够更加高效地使用内存。其中一个方面我们需要知道的是基本的Python对象所占空间的大小,另一方面我们需要知道的是Python在内部到底是如何管理内存的。
基本对象
一个 int 对象占多大空间呢? C/C++程序员会说它是由具体的机器决定的,可能是32为或者64位,因此它最多占8个字节(一个字节8位)。那么在Python中也是如此吗?
下面写一个函数来揭示出对象占多大的空间(某些情况下需要递归,比如某一个对象类型不是基本的数据类型):
1 import sys
2
3 def show_sizeof(x, level=0):
4
5 print "\t" * level, x.__class__, sys.getsizeof(x), x
6
7 if hasattr(x, '__iter__'):
8 if hasattr(x, 'items'):
9 for xx in x.items():
10 show_sizeof(xx, level + 1)
11 else:
12 for xx in x:
13 show_sizeof(xx, level + 1)
我们可以用下面的函数调用来观察不同的基本数据类型所占空间大小:
show_sizeof(None)
show_sizeof(3)
show_sizeof(2**63)
show_sizeof(102947298469128649161972364837164)
show_sizeof(918659326943756134897561304875610348756384756193485761304875613948576297485698417)
在64-bit系统和2.7.8 Python上运行的结果:
<type 'NoneType'> 16 None
<type 'int'> 24 3
<type 'long'> 36 9223372036854775808
<type 'long'> 40 102947298469128649161972364837164
<type 'long'> 60 918659326943756134897561304875610348756384756193485761304875613948576297485698417
可以看到None占了16个字节,int 占了24个字节,是64为系统中C的int64_t 的 3 倍,而且是能够被机器识别的整型。长整型(无限制的精确度)用来表示出了大于263 - 1的整数,所占空间最小为36个字节。而且这个所占空间大小会随着算法中整数的大小线性增长。
Python的float是特定实现的,看上去类似于C中double,但是Python中的 float 不会在数据超过8个字节时终止表示:
show_sizeof(3.141592653589