Python字典大小与对象大小效率

时间:2015-06-23 15:02:28

标签: python object dictionary cpython

在以下示例中使用dictionaryobjects进行操作时,有人可以解释幕后的内存会发生什么:

In [52]: class O(object):
....:         var1 = 'asdfasdfasfasdfasdfasdfasdf'
....:         var2 = 255
....: 

In [53]: dt = {'var1': 'asdfasdfasfasdfasdfasdfasdf', 'var2': 255}

In [55]: o = O()

In [57]: sys.getsizeof(o)
Out[57]: 64

In [58]: sys.getsizeof(dt)
Out[58]: 280

根据上述值,接下来的事情很奇怪

In [68]: sys.getsizeof(o.var1)
Out[68]: 64

In [69]: sys.getsizeof(o.var2)
Out[69]: 24

In [70]: sys.getsizeof(dt['var1'])
Out[70]: 64

In [71]: sys.getsizeof(dt['var2'])
Out[71]: 24

数据结构中的值大小相同,但类型之间的差异让我想知道幕后会发生什么?

该示例是否使objectsdictionaries更有效?

我使用的是Ubuntu 14.04和Python 2.7.6

2 个答案:

答案 0 :(得分:2)

请注意,sys.getsizeof为您提供对象本身的大小,但这不是整个故事。对象具有各种属性,这些属性也有助于整体内存占用。例如,类的实例具有__dict__,其中包含其属性的值:

>>> o = O()
>>> o.__dict__
{}
>>> sys.getsizeof(o.__dict__)
140

注意三件有趣的事情:

  1. 这也是一本字典 - 这个数据结构在Python中引用了很多很多,结果非常优化;
  2. o.__dict__中没有任何内容,因为var1var2类属性,存储在O上,而不是实例属性;和
  3. 即使o.__dict__中没有任何内容,它仍然与dt的大小相同,因为词典初始化时有足够的空间(IIRC)八个键以避免频繁出现在向其添加项目时调整大小(有关字典实现的更多信息,请参阅"The Mighty Dictionary")。
  4. 另请注意,如果我们在两种情况下比较实例加上类的大小,这是一个更公平的比较,则差距缩小:

    >>> sys.getsizeof(o) + sys.getsizeof(O)
    484
    >>> sys.getsizeof(dt) + sys.getsizeof(dict)
    576
    
      

    该示例是否使对象比字典更有效?

    完全没有;首先,正如我所示,对象通常使用字典实现(通过定义__dict__,有一种方法可以不为每个实例创建__slots__在课堂上预先定义的属性,但我不会在这里进入)和词典本身就是对象(虽然内置类型因我赢得的原因而略有不同)!

    一般情况下,除非出现问题,否则不要担心内存细节 - 如果需要状态行为(属性方法),请定义一个类如果您只需要州,请使用字典。

答案 1 :(得分:1)

两个对象的简单比较表明,字典是一个比简单类更复杂的对象:

>>> dt = {}
>>> dir(dt)
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__',  
'__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__',  
'__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__',  
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__',  
'__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get',  
'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem',  
'setdefault', 'update', 'values', 'viewitems', 'viewkeys', 'viewvalues']

针对:

>>> class O(object):
...   var1 = 'asdfasdfasfasdfasdfasdfasdf'
...   var2 = 255
... 
>>> o = O()
>>> dir(o)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', 
 '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__',  
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',  
'__str__', '__subclasshook__', '__weakref__', 'var1', 'var2']