2015-10-23 29 views
6

我很想知道Python中的Bytearray和列表之间的内存管理有何不同。Python中的Bytearray和列表之间的区别

我发现了几个问题,如Difference between bytearray and list,但不完全回答我的问题。

我的问题正是...

from array import array 
>>> x = array("B", (1,2,3,4)) 
>>> x.__sizeof__() 
36 
>>> y = bytearray((1,2,3,4)) 
>>> y.__sizeof__() 
32 
>>> z = [1,2,3,4] 
>>> z.__sizeof__() 
36 

正如我们可以看到有在列表/ array.array之间的尺寸(36个字节为4种元素)为4个元件32个字节的差和一个字节数组( )。有人可以向我解释这是为什么吗?对于字节数组来说它是有意义的,它占用32字节的存储器的4元素(4 * 8 == 32),但是如何解释list和array.array?

# Lets take the case of bytearray (which makes more sense to me at least :p) 
for i in y: 
     print(i, ": ", id(i)) 

1 : 499962320 
2 : 499962336 #diff is 16 units 
3 : 499962352 #diff is 16 units 
4 : 499962368 #diff is 16 units 

为什么两个连续元素之间的差由16单位这里不同,当每个元件仅占据8字节。这是否意味着每个内存地址指针指向一个半字节?

内存分配的整数标准是什么?我读到Python会根据整数的值(如果我错了,纠正我)分配更多的内存,就像内存越大的数字越大。

如:

>>> y = 10 
>>> y.__sizeof__() 
14 
>>> y = 1000000 
>>> y.__sizeof__() 
16 
>>> y = 10000000000000 
>>> y.__sizeof__() 
18 

什么是Python的分配内存的标准是什么?

为什么Python占用更多内存,而C只占用8个字节(我的机器是64位)?当它们完全在整数(2 ** 64)的范围内时?

元数据:

Python版本:'3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit (Intel)]'

机弓: 64位

PS:请指引我的好文章,其中Python的内存管理更好地解释。我花了将近一个小时的时间来解决这些问题,最终在SO中提出了这个问题。 :(

+2

好问题,upvoted。嘿,你很幸运:在我的Linux Xubuntu 64位机上,CPython 3.4.3'y .__ sizeof __()'给了我''28'给'y = 10','y = 1M','32'为'y = 10000000000000' – Pynchia

+0

嗨@Pynchia,矿是一个32位的蟒蛇,虽然我的机器是64位。我不确定,但这可能是原因。让我们等待一些人澄清。 –

回答

1

我不是说这是完整的答案,但也有一些提示,以了解这一点。

bytearray是一个字节序列,并list是对象引用的序列。所以[1,2,3]实际持有内存指针到保存在其他地方存储这些整数。要计算表结构的总内存消耗,我们可以做到这一点(我使用sys.getsizeof到处进一步,它调用__sizeof__加上GC开销)

>>> x = [1,2,3] 
>>> sum(map(getsizeof, x)) + getsizeof(x) 
172 

结果可能是d如果在不同的机器上。

而且,看看这个:

>> getsizeof([]) 
64 

这是因为列表是可变的。为了快速,这个结构分配一些内存范围来存储对象的引用(加上一些存储的元,如列表的长度)。当你添加项目时,下一个存储单元被填入对这些项目的引用。当没有空间存储新的项目时,分配新的更大的范围,在那里复制存在的数据和旧的数据。这叫做动态数组。

您可以通过运行此代码来观察此行为。

import sys 
data=[] 
n=15 
for k in range(n): 
    a = len(data) 
    b = sys.getsizeof(data) 
    print('Length: {0:3d}; Size in bytes: {1:4d}'.format(a, b)) 
    data.append(None) 

我的结果:

Length: 0; Size in bytes: 64 
Length: 1; Size in bytes: 96 
Length: 2; Size in bytes: 96 
Length: 3; Size in bytes: 96 
Length: 4; Size in bytes: 96 
Length: 5; Size in bytes: 128 
Length: 6; Size in bytes: 128 
Length: 7; Size in bytes: 128 
Length: 8; Size in bytes: 128 
Length: 9; Size in bytes: 192 
Length: 10; Size in bytes: 192 
Length: 11; Size in bytes: 192 
Length: 12; Size in bytes: 192 
Length: 13; Size in bytes: 192 
Length: 14; Size in bytes: 192 

我们可以看到,有被用来存储8个存储器地址(每个64位)64个字节。

几乎与bytearray()一样(将第二行更改为data = bytearray()并在最后一行中追加1)。

Length: 0; Size in bytes: 56 
Length: 1; Size in bytes: 58 
Length: 2; Size in bytes: 61 
Length: 3; Size in bytes: 61 
Length: 4; Size in bytes: 63 
Length: 5; Size in bytes: 63 
Length: 6; Size in bytes: 65 
Length: 7; Size in bytes: 65 
Length: 8; Size in bytes: 68 
Length: 9; Size in bytes: 68 
Length: 10; Size in bytes: 68 
Length: 11; Size in bytes: 74 
Length: 12; Size in bytes: 74 
Length: 13; Size in bytes: 74 
Length: 14; Size in bytes: 74 

不同之处在于内存现在用来保存实际的字节值而不是指针。

希望能帮助你进一步调查。

+0

Hi @ anti1869,感谢您的评论。它非常详尽和有用。但是我在评论中有以下问题。我无法在此处添加所有信息,因此在下面添加了另一条评论。谢谢 –

+0

根据你的解释它可以理解为列表,但是为什么字节数组的大小是以56开始的,为什么在达到74之后稳定呢?如果你可以给更多的信息,为什么64和56初始大小,也会很高兴。谢谢 –

+0

检查出数据结构的源代码。在那里你会看到内部容器结构,它在初始化时分配了什么内存。还有非常清晰的可见增长算法。 https://github.com/python/cpython/blob/master/Objects/listobject.c – anti1869

相关问题