методы __getitem__ и __len__?
типа так:
class FooIterator:
def __init__(self, foo):
self.foo = foo
self.idx = 0
def __next__(self):
if self.idx > len(self.foo):
raise StopIteration
result = foo[self.idx]
self.idx += 1
return result
class Foo:
def __iter__(self):
return FooIterator(self)
def __getitem__(self, i):
return i
def __len__(self):
return 5
FooIterator выглядит как стандартный паттерн. Нужно всегда его руками создавать для каждого класса или можно проще?
Все зависит от самого класса
Что значит зависит? Сделать класс итерируемым нужно для foreach loop. Если без iter, то StopIteration прямо в getitem кидать?
Если у класса нет iter, но есть getitem, то при итерации будут возвращаться значения от getitem. В начале 0 передаться, и т.д., пока getitem вроде бы LookupError не выкенет
foreach ждет StopIteration. Кидать StopIteration в getitem выглядит так себе
Не надо кидать StopIteration, я тебе про LookupError говорю
Я перепутал, там должен быть именно IndexError
Работает, спасибо. А подскажите где найти в доке питона, что foreach обрабатывает еще и IndexError? https://docs.python.org/3/reference/compound_stmts.html#for тут что-то очень скудно описано. и здесь https://docs.python.org/3/glossary.html#term-iterable описано что чтобы любой класс стал iterable он может реализовать __iter__ метод или __getitem__, что реализует Sequence семантику (__getitem__() + __len__()). то есть в foreach я бы ожидал если класс реализует getitem + len, то проверка на выход за boundary будет сделана не мной, а внутри foreach, почему это не так?
https://docs.python.org/3/library/functions.html#iter Вот тут написано
Это так потому что тебе всё равно проверять выход за границы
Зачем тебе вообще это нужно всё? Обычно, очень редко необходимо свои коллекции реализовывать
Очень просто, есть класс Dataset и я хочу в foreach стиле по нему пробежаться
Покажи этот класс
Что-то ничего не вижу про IndexError :(
> or it must support the sequence protocol (the getitem() method with integer arguments starting at 0
концептуально что-то такое: class Foo: def __init__(self, foos, bars, bazs): self.foos = foos self.bars = bars self.bazs = bazs size = len(foos) assert size == len(bars) assert size == len(bazs) self.size = size def __getitem__(self, i): if i < 0 or i >= len(self): raise IndexError result = dict( foo=self.foos[i], bar=self.bars[i], baz=self.bazs[i], ) return result def __len__(self): return self.size @staticmethod def load_from_file(filename): with open(filename, "rb") as handle: return pickle.load(handle) def write_to_file(self, filename): with open(filename, "wb") as handle: pickle.dump(self, handle)
это я тоже читал и все это интуитивно понятно, но явное описание того, что foreach словит indexerror exception не нашел где написано в доке, а куда стоит посмотреть, если про это забыл, в сорсы или просозалы pep?
1) Нельзя использовать пикл для долговременного хранения данных (https://t.me/ru_python/1728527) он только для IPC 2) Почему бы сразу не хранить список словарей? Зачем отдельные списки?
Фрагмент, который я показал ссылается на sequence protocol, вот тут разъяснение, что это такое https://docs.python.org/3/reference/datamodel.html#object.__getitem__
1) у меня скорее рисерч проект, поэтому для простоты можно 2) в целом наверное можно хранить и список словарей, но getitem может вернуть чуть больше чем исходный словарь, то есть запроцессить что-нибудь налету и добавить какой-нибудь новый item. ну и когда приходит список словарей, сразу сказать что пришли валидные данные накладно, или проверять уже только в getitem или есть какой-то другой способ кроме как в конструкторе пробежаться по списку и провалидировать каждый элемент/словарь списка.
о, за это спасибо большое!
Обсуждают сегодня