【发布时间】:2019-11-08 19:28:41
【问题描述】:
我目前正在尝试优化一个可以从更少的内存占用中受益的程序。在该程序中,有一些对象存储数据并且从不改变其状态,但它们确实具有功能,例如:
class Extent:
def __init__(self, xmin, ymin, xmax, ymax):
self.xmin = xmin
self.ymin = ymin
self.xmax = xmax
self.ymax = ymax
self.center = ((xmin + xmax) / 2, (ymin + ymax) / 2)
def contains(self, extent: 'Extent'):
# checks if one contains the other
def intersects(self, extent: 'Extent'):
# checks if one intersects the other
在搜索内存节省时,我遇到了__slots__,它阻止类创建__dict__ 用于任意属性分配。这很好,因为我知道对象将具有哪些属性,所以我可以添加它:
class Extent:
__slots__ = ('xmin', 'ymin', 'xmax', 'ymax', 'center')
def __init__(self, xmin, ymin, xmax, ymax):
...
然后我开始探索namedtuple,因为它们占用的内存非常小,缺点是我无法添加方法,除非我将它们子类化:
Boundary = namedtuple('Boundary', ['xmin', 'ymin', 'xmax', 'ymax', 'center'])
class Extent(Boundary):
def contains(self, extent: 'Extent'):
...
def intersects(self, extent: 'Extent'):
...
但这仍然允许创建__dict__,所以我们必须明确声明__slots__:
Boundary = namedtuple('Boundary', ['xmin', 'ymin', 'xmax', 'ymax', 'center'])
class Extent(Boundary):
__slots__ = ()
...
所以我的问题是最后一个例子(namedtuple 子类和__slots__)相对于实现__slots__ 并且不继承任何东西的类有什么好处?
【问题讨论】:
-
嗯,
namedtuple是tuple。所以如果你想要一个序列类型,这是一个很好的方法。否则,您可能只想要一个有插槽的普通课程。 -
@juanpa.arrivillaga 在
namedtuple子类和带插槽的常规类的内存配置文件中有多少对比? -
如果您真的想优化空间,请将您的数据打包成一个字节字符串并完全放弃单独的 Python 对象。
-
@chepner 我还没有看到这个建议,也许你可以在一个例子中详细说明或指向参考?
-
@pstatix 是的,那又怎样?这正是您感兴趣的。如果列表的大小是命名元组子类或自定义类的属性,列表的大小会改变吗?当然,它会考虑类的真实大小。它只是不会递归地为您提供该对象图中所有内容的大小,这可能与不考虑它一样具有误导性。
标签: python class oop python-internals