Как стать автором
Обновить

Комментарии 41

В избранное, немедленно в избранное!
P.S. Большое спасибо за понятное объяснение.
Все это очень хорошо описывается в «Learning Python» Mark Lutz, всем кто не читал настоятельно рекомендую
Именно его сейчас читаю.
Спасибо, стало гораздо понятнее.
Тоже сохранил в избранное.
Кажется, уже было, но в избранном пусть полежит. А то я знаю про них, умею пользоваться, но не использую — в питоне с большим объемом данных не работаю.
Сорри за некропостинг. Это не только с большими данными. К примеру поиск файла с определенными критериями как Вы организовываете?
1.Очень многие сначала пробегаются по директории рекурсивно, создают список, а потом в for-конструкции берут очередной элемент этого списка, т.е. имя файла и уже работают с ним.
2. А это можно значительно улучшить тем, что как только нашли имя файла, то вместо сохранения в список, сразу же yield filename.
def node._get_child_candidates — разве это нормально? Скорее всего имелось в виду — def _get_child_candidates
И действительно, что отмечают и в комментариях на SO:
def anobject.method(): pass is invalid syntax in Python. – J.F. Sebastian Oct 24 '08 at 19:09

Посмотрел в исходники (http://well-adjusted.de/~jrschulz/mspace/mspace-pysrc.html#VPTree._get_child_candidates) — там тоже такого нет. Непонятно, в общем, откуда автор вопроса такое взял.
Заменил.
Пару месяцев назад разобрался с yield именно благодаря этому топику на stackoverflow.
Смутно вспоминаю, что в документации было написано, что не стоит менять список во время итерации по нему.
Это не совсем модификация списка, это такой хитрый способ перебрать дерево.
Разве? У нас же while по candidates.

А в теле цикла candidates.extend.
в данном примере нет итерации по списку. ;)
возможно, чтобы исключить путаницу, авторам нужно было воспользоваться collections.deque для реализации стека, а не list.
Был неправ. Там while candidates и candidates.pop, а не for… in candidates.
Посмотрел невнимательно. Типичный стек.
Наверное, также стоит добавить, что итерирование завершается за счет выбрасывания исключения StopIteration. Т.е. вот этот код

for i in gen:
     print i

на самом деле работает как-то так:

try:
    while True:
        print gen.next()
catch StopIteration:
    pass


Это важно понимать, если для итерирования генеретора не достаточно констрункции for ... in, и нужно закрутить что-то с while'ом.
Только конечно не catch, а except. )
Еще, в статье не упоминается, что в коде генератора также можно использовать return, но без возвращаемого значения, который воспринимается, как завершение итерирования и аналогичен raise StopIteration
НЛО прилетело и опубликовало эту надпись здесь
Я вам попытался ответить на этот комментарий, но попал в top-level: habrahabr.ru/blogs/python/132554/#comment_4401013 — взгляните, там хорошая ссылка.
А насколько в питоне исключения быстро работают? В некоторых языках, например жава, не рекомендуется использовать исключения для штатных ситуаций, потому что это работает не очень быстро. В питоне, получается, такого нет.
Питон не позиционируется как системный язык, а потому в вопросе использования исключений принято исходить из удобства. Ситуация, когда функция возвращает «не успешность» своего выполнения как значение (return) является скорее антипаттерном.
Например, через yield генератор может не только возвращать значение, но и принимать произвольный аргумент:

Более того, это само интересное в yield-е и есть. yield i разжёвывать и смысла особого нет — ну генераторы и генераторы. А вот j = yield i позволяет делать сопроцедуры (coroutines). Которые открывают совершенно новые возможности в Python-е, от цепочек «потребителей» (в смысле, они являются как бы антонимом к «генераторам», но, точно так же, как и генераторы, могут объединяться в цепочки) до кооперативной многозадачности (!!!).

На эту тему есть хорошая (правда, длинная и на английском) презентация: www.dabeaz.com/coroutines/Coroutines.pdf
НЛО прилетело и опубликовало эту надпись здесь
«А никто не обещал, что будет легко» :)

На самом деле, метафора generator vs consumer очень хорошо подходит для первого сценария использования.
Ну, а кооперативная многозадачность… впрочем, вряд ли кому понадобится заниматься ей на таком низком уровне (а не хотя бы на уровне eventlet/gevent).
На основе этого сделан inline callback в асинхронных фреймворках twisted, web tornado.
Шикарная вещь, узнал об этом буквально неделю назад. Понял, что во многих местах нужно было использовать именно g.send() вместо костылей.
вот ещё статья, про использование генераторов для управления задачами: www.kamaelia.org/MiniAxon.html.
Итерация это процесс, включающий итерируемые объекты (реализующие метод __iter__()) и итераторы (реализующие __next__())

Только не __next_()_, а next().
Отличное изложение, все понятно и по делу.
>Генераторам же предшествуют итераторы.

Всё никак не могу понять: в теории итераторы и генераторы — это просто множества со схожими свойствами/интерфейсами или одно из них является подмножеством (или наследником, если угодно) другого? Является ли корректным высказывание: «Любой итератор — это генератор»?
Бывают iterators, iterables и generators.
Iterable (iterable interface) — интерфейс, позволяющий итерироваться (метод next/__next__ и raise StopIteration в конце).
Iterator — объект с iterable interface.
Generator — функция, возвращающая iterator.

The Python Tutorial — Classes
Building Skills in Python — Iterators and Generators
Да StackOverflow уже не торт, там всякие Димы Маликовы тусуются.
НЛО прилетело и опубликовало эту надпись здесь
Ужасно!
В объяснении удалось избежать функциональных замыканий, continuations и сопроцедур!
а в питоне поддерживается возбуждение исключения в месте yield?
НЛО прилетело и опубликовало эту надпись здесь
Требую мануал по рекурсивным генераторам! :)
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории