Python中len()方法和sys.getsizeof()方法有什么区别?

40
当我运行下面的代码时,我得到了分别为3和36的答案。
x ="abd"
print len(x)
print sys.getsizeof(x)

有人能够解释一下它们之间的区别吗?


3
可能OP认为Python字符串和C字符串类似,每个字符占一个字节,再加上一个null字节。 - Martijn Pieters
6
不确定为什么这个被关闭了。两年后,答案正好是我想要的,而且对于任何需要理解字符串大小的人来说都非常相关,以我的看法。 - Realistic
2个回答

81
他们根本不是同一件事情。完全不同len() 查询容器中包含的项目数。对于字符串,这是字符数:
返回对象的长度(项目数)。参数可以是序列(字符串、元组或列表)或映射(字典)。 sys.getsizeof() 返回对象的内存大小
返回对象的大小(以字节为单位)。对象可以是任何类型的对象。所有内置对象都将返回正确的结果,但对于第三方扩展来说,这并不一定成立,因为它是实现特定的。
Python字符串对象不是简单的字符序列,每个字符占用1个字节。
具体而言,sys.getsizeof() 函数包括垃圾收集器的开销(如果有的话):

getsizeof() 调用对象的 __sizeof__ 方法,如果对象由垃圾回收器管理,则会添加额外的垃圾回收器开销。

字符串对象不需要被跟踪(它们不能创建循环引用),但是字符串对象需要比每个字符的字节更多的内存。在 Python 2 中,__sizeof__ 方法返回(在 C 代码中):

Py_ssize_t res;
res = PyStringObject_SIZE + PyString_GET_SIZE(v) * Py_TYPE(v)->tp_itemsize;
return PyInt_FromSsize_t(res);

这里的PyStringObject_SIZE是该类型的C结构头大小,PyString_GET_SIZE基本上与len()相同,Py_TYPE(v)->tp_itemsize是每个字符的大小。在Python 2.7中,字节字符串的每个字符大小为1,但是它是PyStringObject_SIZE让你感到困惑;在我的Mac上,该大小为37字节:

>>> sys.getsizeof('')
37

对于unicode字符串,每个字符的大小会增加到2或4(取决于编译选项)。在Python 3.3及更高版本中,Unicode字符串每个字符占用1到4个字节,具体取决于字符串的内容
对于像字典或列表这样引用其他对象的容器,所给出的内存大小仅覆盖容器使用的内存和用于引用那些其他对象的指针值。没有直接的方法可以包括“包含”的对象的内存大小,因为这些相同的对象可能在其他地方有更多的引用,并且不一定由单个容器拥有。
文档是这样说明的:

只计算直接归因于对象的内存消耗,而不计算它引用的对象的内存消耗。

如果您需要计算容器及其引用的任何内容的内存占用量,您将需要使用某种遍历到这些包含对象并获取其大小的方法;文档指向了一个递归配方

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接