seb*_*314 10 python tuples class list data-structures
我在元组/列表中存储了大量复杂数据,但更喜欢使用小包装类来使数据结构更容易理解,例如
class Person:
def __init__(self, first, last):
self.first = first
self.last = last
p = Person('foo', 'bar')
print(p.last)
...
Run Code Online (Sandbox Code Playgroud)
会优先于
p = ['foo', 'bar']
print(p[1])
...
Run Code Online (Sandbox Code Playgroud)
然而,似乎有一个可怕的内存开销:
l = [Person('foo', 'bar') for i in range(10000000)]
# ipython now taks 1.7 GB RAM
Run Code Online (Sandbox Code Playgroud)
和
del l
l = [('foo', 'bar') for i in range(10000000)]
# now just 118 MB RAM
Run Code Online (Sandbox Code Playgroud)
为什么?我有没有想到的任何明显的替代解决方案?
谢谢!
(我知道,在这个例子中,'wrapper'类看起来很傻.但是当数据变得更复杂和嵌套时,它会更有用)
ran*_*mir 11
正如其他人在他们的答案中所说,你必须生成不同的对象才能进行比较.
那么,让我们比较一些方法.
tuplel = [(i, i) for i in range(10000000)]
# memory taken by Python3: 1.0 GB
Run Code Online (Sandbox Code Playgroud)
class Personclass Person:
def __init__(self, first, last):
self.first = first
self.last = last
l = [Person(i, i) for i in range(10000000)]
# memory: 2.0 GB
Run Code Online (Sandbox Code Playgroud)
namedtuple(tuple+ __slots__)from collections import namedtuple
Person = namedtuple('Person', 'first last')
l = [Person(i, i) for i in range(10000000)]
# memory: 1.1 GB
Run Code Online (Sandbox Code Playgroud)
namedtuple基本上是一个扩展tuple和使用__slots__所有命名字段的类,但它添加了字段getter和一些其他辅助方法(如果调用,你可以看到生成的确切代码verbose=True).
class Person + __slots__class Person:
__slots__ = ['first', 'last']
def __init__(self, first, last):
self.first = first
self.last = last
l = [Person(i, i) for i in range(10000000)]
# memory: 0.9 GB
Run Code Online (Sandbox Code Playgroud)
这是namedtuple上面的精简版.一个明显的赢家,甚至比纯元组更好.
使用会__slots__减少内存占用(在我的测试中从1.7 GB到625 MB),因为每个实例不再需要保存dict来存储属性.
class Person:
__slots__ = ['first', 'last']
def __init__(self, first, last):
self.first = first
self.last = last
Run Code Online (Sandbox Code Playgroud)
缺点是您不能再在创建实例后向其添加属性; 该类仅为属性中列出的__slots__属性提供内存.