Python 字典大小与对象大小效率
Python dictionary size vs object size efficiency
有人可以解释在下面的例子中使用 dictionary
和 objects
操作时 memory 在幕后发生了什么:
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
数据结构中的值大小相同,但类型之间的差异让我想知道幕后发生了什么?
该示例是否使 objects
比 dictionaries
更有效?
我使用 Ubuntu 14.04 和 Python 2.7.6
两个对象的简单比较表明字典比简单的对象复杂得多 class:
>>> 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']
请注意,sys.getsizeof
为您提供了 对象本身的大小 ,但这并不是全部。对象具有各种 属性 ,这些属性也会影响整体内存占用。例如,一个 class 的实例有一个 __dict__
,它保存它的属性值:
>>> o = O()
>>> o.__dict__
{}
>>> sys.getsizeof(o.__dict__)
140
注意三件有趣的事情:
- 这也是一个字典 - 这个数据结构在 Python 中被 大量使用 ,因此得到了非常好的优化;
o.__dict__
中没有任何内容,因为var1
和var2
是class属性,存储在O
,不是实例属性;和
- 即使
o.__dict__
中没有任何内容,它仍然与 dt
大小相同,因为字典已使用足够的 space 初始化 (IIRC) 八个键以避免频繁调整大小您向它们添加项目(有关词典实现的更多信息,请参阅 "The Mighty Dictionary")。
另请注意,如果我们在两种情况下比较实例 加上 class 的大小,这是一个更公平的比较,差距会缩小:
>>> sys.getsizeof(o) + sys.getsizeof(O)
484
>>> sys.getsizeof(dt) + sys.getsizeof(dict)
576
Does the example makes objects more effective over dictionaries?
完全没有;一方面,正如我所展示的,对象通常是 使用 字典实现的(有一种方法可以不为每个实例创建 __dict__
,通过定义 __slots__
class 上的预定义属性,但我不会在这里深入讨论)和字典本身就是对象(尽管内置类型略有不同,原因我不会详述)!
一般来说,不要担心内存细节,除非它成为问题 - 如果你需要状态 和 行为(属性 和方法),如果你只需要状态就使用字典。
有人可以解释在下面的例子中使用 dictionary
和 objects
操作时 memory 在幕后发生了什么:
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
数据结构中的值大小相同,但类型之间的差异让我想知道幕后发生了什么?
该示例是否使 objects
比 dictionaries
更有效?
我使用 Ubuntu 14.04 和 Python 2.7.6
两个对象的简单比较表明字典比简单的对象复杂得多 class:
>>> 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']
请注意,sys.getsizeof
为您提供了 对象本身的大小 ,但这并不是全部。对象具有各种 属性 ,这些属性也会影响整体内存占用。例如,一个 class 的实例有一个 __dict__
,它保存它的属性值:
>>> o = O()
>>> o.__dict__
{}
>>> sys.getsizeof(o.__dict__)
140
注意三件有趣的事情:
- 这也是一个字典 - 这个数据结构在 Python 中被 大量使用 ,因此得到了非常好的优化;
o.__dict__
中没有任何内容,因为var1
和var2
是class属性,存储在O
,不是实例属性;和- 即使
o.__dict__
中没有任何内容,它仍然与dt
大小相同,因为字典已使用足够的 space 初始化 (IIRC) 八个键以避免频繁调整大小您向它们添加项目(有关词典实现的更多信息,请参阅 "The Mighty Dictionary")。
另请注意,如果我们在两种情况下比较实例 加上 class 的大小,这是一个更公平的比较,差距会缩小:
>>> sys.getsizeof(o) + sys.getsizeof(O)
484
>>> sys.getsizeof(dt) + sys.getsizeof(dict)
576
Does the example makes objects more effective over dictionaries?
完全没有;一方面,正如我所展示的,对象通常是 使用 字典实现的(有一种方法可以不为每个实例创建 __dict__
,通过定义 __slots__
class 上的预定义属性,但我不会在这里深入讨论)和字典本身就是对象(尽管内置类型略有不同,原因我不会详述)!
一般来说,不要担心内存细节,除非它成为问题 - 如果你需要状态 和 行为(属性 和方法),如果你只需要状态就使用字典。