Comments 45
P.S. Большое спасибо за понятное объяснение.
Тоже сохранил в избранное.
1.Очень многие сначала пробегаются по директории рекурсивно, создают список, а потом в for-конструкции берут очередной элемент этого списка, т.е. имя файла и уже работают с ним.
2. А это можно значительно улучшить тем, что как только нашли имя файла, то вместо сохранения в список, сразу же yield filename.
def node._get_child_candidates — разве это нормально? Скорее всего имелось в виду — def _get_child_candidatesdef 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) — там тоже такого нет. Непонятно, в общем, откуда автор вопроса такое взял.
А в теле цикла candidates.extend.
возможно, чтобы исключить путаницу, авторам нужно было воспользоваться collections.deque для реализации стека, а не list.
Посмотрел невнимательно. Типичный стек.
Как это нет, вроде как раз есть. Каждый раз candidates модифицируются ссылками на узлы, при вызове extend. То, что каждый раз выкусывается самый ранний делу не помогает. Или я что-то не понял.
StopIteration. Т.е. вот этот код
for i in gen:
print i
на самом деле работает как-то так:
try:
while True:
print gen.next()
catch StopIteration:
pass
Это важно понимать, если для итерирования генеретора не достаточно констрункции
for ... in, и нужно закрутить что-то с while'ом.catch, а except. )return, но без возвращаемого значения, который воспринимается, как завершение итерирования и аналогичен raise StopIterationНапример, через yield генератор может не только возвращать значение, но и принимать произвольный аргумент:
Более того, это само интересное в yield-е и есть. yield i разжёвывать и смысла особого нет — ну генераторы и генераторы. А вот j = yield i позволяет делать сопроцедуры (coroutines). Которые открывают совершенно новые возможности в Python-е, от цепочек «потребителей» (в смысле, они являются как бы антонимом к «генераторам», но, точно так же, как и генераторы, могут объединяться в цепочки) до кооперативной многозадачности (!!!).
На эту тему есть хорошая (правда, длинная и на английском) презентация: www.dabeaz.com/coroutines/Coroutines.pdf
Итерация это процесс, включающий итерируемые объекты (реализующие метод __iter__()) и итераторы (реализующие __next__())
Только не __next_()_, а next().
Всё никак не могу понять: в теории итераторы и генераторы — это просто множества со схожими свойствами/интерфейсами или одно из них является подмножеством (или наследником, если угодно) другого? Является ли корректным высказывание: «Любой итератор — это генератор»?
Iterable (iterable interface) — интерфейс, позволяющий итерироваться (метод next/__next__ и raise StopIteration в конце).
Iterator — объект с iterable interface.
Generator — функция, возвращающая iterator.
The Python Tutorial — Classes
Building Skills in Python — Iterators and Generators
В объяснении удалось избежать функциональных замыканий, continuations и сопроцедур!
Может случиться так, что потомков много и хранить их всех в памяти не хочется.
Не понял. А вот этот код тогда что делает?
candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
Допустим в candidates лежат два элемента. Если _get_child_candidates возвращает генератор, который при вызове вернет еще два (т.е. и правый и левый потомки есть), то candidates увеличится на два элемента? Или же у него будет состояние "первые два элемента в нулевой и первой ячейках, а если попросят, что в третьей, то нужно будет вызвать генератор"?
Или же здесь candidates.extend сразу вычитывает весь генератор, который вернул метод _get_child_candidates, и добавляет все элементы из генератора в конец candidates сразу?
Когда вы создаёте список, используя генераторное выражение, вы создаёте также итератор:
Я бы был аккуратнее, потому что есть ещё вот такая конструкция (круглые скобки):
myList = (x * x for x in range(3))И вот это как раз я бы назвал генераторным выражением. Как минимум, я бы добавлял в скобках оригинальное название терминов, которые трудно переводятся (в данном случае это list comprehension).
Всё, к чему можно применить конструкцию «for… in...», является итерируемым объектом:
А зачем вы переводите так, что каждый раз у вас новый термин ? В оригинале заголовок Iterables - вы его перевели как Итераторы . Тут то же слово в оригинале, но теперь он у вас итерируемый объект .
Ваш код будет вызываться каждый раз, когда for обращается к генератору.
Вводит в заблуждение. Оригинал: "Then, your code will continue from where it left off each time for uses the generator." - Каждый раз, когда for обращается к генератору на очередной итерации, ваша функция продолжит с того места, где она была прервана на предыдущей итерации. Как-то так.
Этот код содержит несколько меньших частей:
Там "smart parts", а не "small parts".
Цикл итерируется по списку, но списко расширяется во время итерации :-) Это лаконичный способ обойти все сгрупиррованные данные, зоть это и немного опасно, так как может обернуться бесконечным циклом. В таком случае
Тут вообще с точностью до наоборот. Не в таком случае, а в этом (имеется в виду случай, описанный в коде). А у вас тут как будто вы дальше продолжаете обосновывать предыдущее утверждение про опасность бесконечного цикла. Хотя автор просто описывает дальше, как код работает.
который ожидает на вход что-нибудь итерируемое и добавляет его значения к списку.
Теперь iterable превратилось в что-нибудь итерируемое.
Дальше уже не стал корректировать.
Перевод на троечку. Лучше прочтите оригинал.
Как работает yield