Найти - Пользователи
Полная версия: Лист и тип возвращаемых элементов
Начало » Python для новичков » Лист и тип возвращаемых элементов
1
Levitanus
Делаю лист-подобный класс, и от него требуется по getitem выдавать функционирующий объект, инициализированный положенным значением.
Реализацией в лоб был МАП инициализационной секвенции и последующее создание объектов по append. Но оказалось, что это сильно дорого, и может повесить выполнение на 10 мин при одном листе на 1М элементов.
Вторая попытка в виде отдельной обработки случаев доступа к элементам на местах, вроде была шустрой, но выросла в кашу кода. Сейчас переписываются заново. Думаю, не сяду ли опять в лужу, если буду создавать объекты в getitem по запросу и кешировать их?
DamMercul
Почти ничего не понял, но понимаю в чем проблема. Использую модуль queue, класс Queue. Он вполне себе подходит. 1М объектов для него - фигня, никаких MemoryError не будет, этот модуль не пальцем деланый. А получить 1 объект стоящий последний можно используюя метод .get(), положить .put(). Пример:

 from queue import Queue
queue = Queue()
# Make 1m queue.put(smthing)
object_ = queue.get()

Надеюсь помогло
P.S. Если сможешь - объясни по-проще для сметных пожалуйста)
Levitanus
Ох, с планшета ахинея всякая пишется…
Попробую завтра хоть 3g нормальный поймать - точнее ситуацию опишу.
Очередь - не совсем то. Проблема в создании кучи объектов без прямой надобности.
Levitanus
Прошу прощения, только получилось завести интернет на ноут.
В общем, суть проблемы:
Есть лист-подобный класс, который на вход принимает секвенцию. Он может принимать как встроенный тип int, так и кастомный, назовем его Int, у которого есть property value.
При приеме элемента типа Int он вызывает его метод value и сохраняет в приватный list значение int.
А при вызове __getitem__ он должен отдавать уже новый объект Int со своими специфическими атрибутами (допустим,
 my_IntList[0].name == f'{my_IntList.name}[0]'
).
Вот в первой редакции все выглядело так:
 class IntList:
    def __init__(self, name, seq):
        self._name = name
        self._seq_duck_type(seq)
        self.__seq = self._make_seq(seq)
    def _make_seq(self, seq):
        for idx, item in enumerate(seq):
            if isinstance(item, Int):
                item = item.value
            self.__seq.append(Int(name=f'{self._name}[{idx}]',
                                  value=item))
    def __getitem__(self, idx):
        idx = self._idx_duck_type(idx)
        return self.__seq[idx]
но оказалось, что это вообще ни разу не быстро, ибо
 for item in seq:
    self.__seq.append(item)
по времени выполнения отличается кардинльно от
 for item in seq:
            self.__seq.append(Int(item))
Пожтому по второму проходу был использован вариант сохранения только значений, и возврата их же.
Но последующей обработкой поступающих значений в духе (ну это уже утрированно):
 def func(val, idx=None):
    if idx is None:
        return process(val.name, val.value)
    if isinstance(val, IntList):
        return process(f'{val.name}[{idx}]', val[idx])
короче, каша. Хотя по скорости обработки удоветворительно, т.к. объявление больших массивов - не редкость, а прогон по всем элементам - уже не такая.

Вот сейчас третий проход
выглядит все так:
 class IntList(KspVar):
    def __init__(self, name, ref_type=None, item_type=None,
                 size=None, seq=None):
        super().__init__(name,
                         ref_type=ref_type)
        if not isinstance(item_type, type):
            raise TypeError('item_type has to be subclass of KspVar')
            if not issubclass(item_type, KspVar):
                raise TypeError(
                    'item_type has to be subclass of KspVar')
        self._item_type = item_type
        self.__name = name
        if seq is not None:
            self._seq = self._init_seq(seq)
        else:
            self._seq = list()
        if size is not None:
            if self._seq:
                if len(self._seq) < size:
                    raise AttributeError(
                        'size has to be greater or equal length of seq')
            self._size = size
            self._init_size = size
        else:
            self._size = 0
            self._init_size = None
        self._cashed = [None] * self._size
        def _init_seq(self, seq):
            if not isinstance(seq, list):
                raise TypeError('seq has to be instance of list')
            for item in seq:
                if not isinstance(item, self.ref_type):
                    raise TypeError(
                        'all items of seq have to be instances of' +
                        f'{self.ref_type}')
            return seq
        @property
        def item_type(self):
            return self._item_type
        def extend(self, seq):
            if not isinstance(seq, list):
                raise TypeError('has to be list')
            for val in seq:
                self.append(val)
        def __getitem__(self, idx):
            idx = self._check_idx(idx)
            self._check_cashed_item(idx)
            return self._cashed[idx]
        def __setitem__(self, idx, val):
            idx = self._check_idx(idx)
            self._seq[idx]
            self._check_cashed_item(idx)
            self._cashed[idx] <<= val
        def _check_idx(self, idx):
            if not isinstance(KspIntVar, int):
                raise TypeError('has to be int or int KspIntVar')
            if isinstance(idx, KspIntVar):
                idx = idx.val
            return idx
        def _check_cashed_item(self, idx):
            if self._cashed[idx] is None:
                self._cashed[idx] = \
                    self._item_type(name=f'{self.__name}[{idx}]',
                                    value=self._seq[idx])
на что я еще в перспективе могу напороться, и в плане архитектуры, и в плане производительности?
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB