我将让您的namedtuple x插槽这个特定问题分开,然后集中讨论您的内存节省问题。因为元组x带槽的属性可能并且大小会有所不同,但会有所不同-但是使用这两个属性时,必须保留完整的Python对象作为数字本身。
可能有一个类,可以将数据保留为数组中的打包字节,并根据需要懒惰地将属性转换为Python数字。在内存方面,这将是一个赢家,因为Python中的数字是一个完整的对象,最小大小为24个字节(在64位平台上)。
如果懒惰地获取数字会导致性能问题,则可以将类移至cython,并让操作使用每个对象中的本机压缩数字。
总而言之,有效的方法可能是专门的Sequence类,它将包装NumyArray以及序列中对象的数据以及从该序列中作为元素检索的短暂对象。
好消息是numpy已经提供了此功能-它允许数组由具有自定义dtype
的对象组成,甚至还有np.void
定义的结构类型基类它的dtype-可以具有其他功能。
下面的代码可以在numpy数组中保存一个“ Extents”类,每个实例恰好占用了数据所需的字节数。优点是可以使用扩展的numpy数据类型-例如,如果需要考虑内存并且32bit FP值足以满足您的需要,请使用“ float32”(“ f4”)。
您实际上可以只使用带有自定义dtype的原始np数组-此代码显示了如何添加一些钟声来具有您的“ center”属性,并能够访问xmin等作为属性,比仅使用映射语法(seq [0] [“ xmin”]):
from collections.abc import MutableSequence
import numpy as np
class Extent(np.void):
attrs = "xmin ymin xmax ymax".split()
dtype = np.dtype([(attr,"f8") for attr in attrs])
def __getattr__(self,attr):
return self.__getitem__(attr)
def __setattr__(self,attr,value):
if value in self.attrs:
return self.__setitem__(self,value)
return super().__setattr__(attr,value)
@classmethod
def store(self,storage,xmin,ymin,xmax,ymax):
storage.append((xmin,ymax))
return storage[storage.last_item - 1]
def contains(self,extent: 'Extent'):
pass
# checks if one contains the other
def intersects(self,extent: 'Extent'):
pass
# checks if one intersects the other
@property
def center(self):
return ((self.xmin + self.xmax) / 2,(self.ymin + self.ymax) / 2)
def __repr__(self):
return f"Extent <{self.xmin},{self.ymin},{self.xmax},{self.ymax}>"
class ExtentList:
def __init__(self,max_size):
self.last_item = 0
self.data = np.zeros(max_size,dtype=Extent)
def __getitem__(self,index):
return self.data[index]
def __setitem__(self,index,value):
self.data[index] = value
def append(self,extent):
self.data[self.last_item] = extent
self.last_item += 1
def __iter__(self):
for i in range(self.last_item):
yield self.data[i]
def __repr__(self):
return f"ExtentList <{self.data[:self.max_size]!r}>,max={self.max_size}"
在交互式终端上:
In [63]: values = ExtentList(10)
In [64]: v = Extent.store(values,10,20,20)
In [65]: v
Out[65]: Extent <10.0,10.0,20.0,20.0>
In [66]: v.center
Out[66]: (15.0,15.0)
此外-这种方法允许您的属性就地可变:
In [73]: v.xmax = 40
In [74]: v.center
Out[74]: (25.0,15.0)
唯一的缺点是您无法轻松调整numpy数组的大小-因此,我需要为结尾保留一个内部索引,而您必须设置max-size。如果max-size的变化太大,围绕如何调整numpy-array的大小的方法很多,您必须将逻辑添加到容器类中才能做到这一点,这受Python本身用于分配大小的逻辑的启发列表。
本文链接:https://www.f2er.com/3135514.html