Я расскажу о вашем конкретном вопросе о слот namedtuple x и остановлюсь на проблеме экономии памяти. Поскольку атрибуты кортежей х слотов могут и будут различаться по размеру на несколько байтов, но при использовании любого из них вы должны содержать полные объекты Python как сами числа.
Можно иметь класс, который будет сохранятьданные упакованы байтами в массиве и лениво выдают ваши атрибуты в виде чисел Python по мере необходимости. Что касается памяти, это было бы победителем, так как число в Python - это полный объект с минимальным размером 24 байта (на 64-битных платформах).
Если получение чисел лениво становится проблемой производительности, вы можете переместитьот вашего класса до Cython, и в операциях используются исходно упакованные числа в каждом из ваших объектов.
В целом, допустимым подходом может быть специализированный класс Sequence, который обернет NumyArray данными для ваших объектов впоследовательности и эфемерные объекты, которые извлекаются как элементы из этой последовательности.
Хорошая новость заключается в том, что numpy уже предлагает эту функцию - она позволяет составлять массивы из объектов с пользовательскими dtype
, и дажеnp.void
базовый класс структурного типа, который определяется его типом d - который может иметь дополнительные функциональные возможности.
Код ниже может содержать класс "Extents" внутри массива numpy, причем каждый экземпляр принимает ровно числобайтов, необходимых для данных. С тем преимуществом, что вы можете использовать расширенные numy-типы данных - например, использовать «float32» («f4»), если память представляет собой проблему, и вам достаточно 32-битного значения FP.
Вы могли бы на самом делепросто используйте необработанный массив np с пользовательским типом dtype - этот код показывает, как вы можете добавить некоторые навороты, чтобы иметь свойство "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, attr, value)
return super().__setattr__(attr, value)
@classmethod
def store(self, storage, xmin, ymin, xmax, ymax):
storage.append((xmin, ymin, xmax, 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, 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-массивов, и для этого вам нужно будет добавить логику в класс контейнера, вдохновленный логикой, которую сам Python использует для распределения размера длясписки.