1

От продавца до Big Data Scientist #11

Прошлый пост - От продавца до Big Data Scientist #10


Прошлый раз я писал  в среду, поэтому в общем ничего сильно не поменялось, очередная тема которую я пока ну вот вообще не понимаю! Итераторы и генераторы. Точнее вроде как после просмотра кучи левых лекция я вроде и понял, но реализовать в коде пока не получается. Надо получше разобраться  с yield. Да и вообще. Я всё меньше понимаю что тут вообще происходит =) Мой мозг просто отказывается думать уже. Хотя я даю ему перерывчики по паре дней, но это не спасает. Задачи, которые решались ранее были понятны, всегда ясно что на входе и что на выходе, здесь же я часто не могу сформулировать и ход мыслей и итог, а иногда не понимаю что вообще от меня просят. Жуть. Но цель закончить-таки этот курс стоит, дальше наверное с SQL начну разбираться, а то вроде без него вообще никуда.

Сильно распространяться не о чем, так что, до понедельника :)

Вы смотрите срез комментариев. Показать все
0
Автор поста оценил этот комментарий
Какой именно аспект работы с генераторами вызывает у вас вопросы? Я когда-то давным давно проходил тот курс и вроде все было даже слишком тривиально
раскрыть ветку (17)
0
Автор поста оценил этот комментарий

Да пока я даже не могу сформулировать. Если в классе определена ф-ия __next__, то это класс становится итератором? Верно? Если в Классе определена ф-ия __iter__, то этот класс становится итерируемым. А если и та и другая, то класс может итерировать сам себя? Как это? %( Притом почему-то итерировать сам себя он может только один раз? А если итерируемый экземпляр итерирует другой экземпляр, являющийся итератором, то можно итерировать много раз? Что такое Генератор? Он не содержит значения, а генерирует их при запросе? Как работает Yield? У меня прям каша в голове от попытки это всё осмыслить..

раскрыть ветку (16)
0
Автор поста оценил этот комментарий

Вы по первым пунктам вы правы - объект считается итерируемым если для него определена функция __iter__, которая возвращает итератор. Итератор, это то, что умеет в функцию next.

Насчет того кто и сколько раз умеет итерироваться: постановка вопроса вообще не вполне корректна, суть дела тут в наличии у итератора некоего состояния и места где это состояние хранится.

В случае, если мы итерируем список, это состояние определяется (помимо самого списка) текущей позицией в нем. Когда вы сохраняете позицию в самом объекте списка, вы технически можете обеспечить многократность его итерирования, но для этого вам придется научиться сбрасывать счетчик позиции, если же вы в функции __iter__ создаете одноразовые объекты с этим можно не заморачиваться.

НО! у итератора вообще может не быть состояния в таком случае он будет перебираться бесконечно либо он может определять необходимость бросить StopIteration по каким-то внешним признакам (код ответа от сервера, наличие файла и т.д.)


Давайте рассмотрим следующий класс:


class A:

    def __iter__(self):

        return self

    def __next__(self):

        return random.randint(0,100)


Сколько "раз" оно может итерироваться? Лично я бы сказал - нисколько.

А если вот так:


class B:

    def __init__(self, list):

        self.list = list

        self.counter = 0

    def __iter__(self):

        return self

    def __next__(self):

        if self.counter < len(self.list):

            self.counter += 1

            return self.list[self.counter-1]

        else:

            self.counter = 0

            raise StopIteration


Этот класс может итерироваться сколько угодно раз.

раскрыть ветку (15)
0
Автор поста оценил этот комментарий

З.Ы. генератор - очень простая штука (по крайней мере внешне), но переходить к ним стоит только после полного понимания того как работают итераторы в целом, т.к. каждый генератор является итератором

раскрыть ветку (14)
0
Автор поста оценил этот комментарий

Ну спаси меня пожалуйста! :D

раскрыть ветку (13)
0
Автор поста оценил этот комментарий

Портянка выше вам понятна? Вопрос о том в чем разница между возвращением себя как итератора и созданием отдельного объекта снят?

раскрыть ветку (12)
0
Автор поста оценил этот комментарий

Я нихуя не пойму. Требуется принять последовательность, проверить её тремя функциями и вернуть только значения, проходящие фильтр из тех функций.

Приведу собственно как реализован метод next. Для начала проверяю не закончился ли список, потом идут переменные для проверки прохождения фильтра из функций, собственно фильтр (сами функции внутри тела класса их нет смысл показывать) Затем если проверка прошла я добавляю к временному списку (z) значение ,если нет, то перехожу к следующему значению. Возвращаю полученный список.

def __next__(self):

____for i in self.iterable:

________if self.count < len(self.iterable):

____________pos = 0

____________neg = 0

____________for func in self.funcs:

________________if func(i):

____________________pos += 1

________________else:

____________________neg += 1

____________if self.judge(pos, neg) == True:

________________self.z.append(i)

________________self.count += 1

____________else:

________________raise StopIteration

____return self.z

Внимание вопрос: когда идёт вызов: print(list(multifilter(a, mul2, mul3, mul5))), (где multifilter - имя класса, a - последовательность значений списком, mul - функции фильтры), моё решение выдаёт ответ но в двойных квадратных скобках [[2, 3, 5]] например. А должно быть в одинарных: [2, 3, 5]. Я так понимаю фигня в том что и значения в списке хранятся и запрашиваются через список, поэтому двойные скобки. Но как их хранить вообще без ничего? или их не надо хранить? Я нифига не пойму

раскрыть ветку (11)
0
Автор поста оценил этот комментарий

так, давайте разбираться:

1) что должна возвращать функция __next__ у итератора?

2) что она возвращает в реализации выше?

раскрыть ветку (10)
0
Автор поста оценил этот комментарий

1. Следующее значение?

2. Весь список?

раскрыть ветку (9)
0
Автор поста оценил этот комментарий

Смотрите, вся идея подобного итератора в том, что он обрабатывает одно значение за раз, и вам нужно так или иначе хранить текущий индекс чтобы при следующем вызове "вспомнить" где же вы остановились.

Посмотрите мои примеры выше, они должны навести вас на мысль

раскрыть ветку (7)
0
Автор поста оценил этот комментарий

Переделал, почему-то вместо отфильтрованных значений стали возвращаться None, хотя я так и не понял, как до reurn вообще доходил интерпритатор. Но, подглядел на форуме решение с рекурсией. Добавил - заработало, но степик всё равно не принимает решение.

def __next__(self):

____if self.count < len(self.iterable):

________pos = 0

________neg = 0

________self.count += 1

________for func in self.funcs:

____________if func(self.iterable[self.count-1]):

________________pos += 1

____________else:

________________neg += 1

________if self.judge(pos, neg) == True:

____________return self.iterable[self.count-1]

________else: return self.__next__()

____else:

________raise StopIteration

раскрыть ветку (6)
0
Автор поста оценил этот комментарий

Именно, т.е. ошибку мы уже нашли, осталось ее исправить)

Подсказка: если список не нужно возвращать целиком, то скорее всего его и хранить не нужно

Вы смотрите срез комментариев. Чтобы написать комментарий, перейдите к общему списку