Как точно работает понимание генератора?

Что понимает генератор? Как это работает? Я не мог найти учебник об этом.

Ответ 1

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

>>> my_list = [1, 3, 5, 9, 2, 6]
>>> filtered_list = [item for item in my_list if item > 3]
>>> print filtered_list
[5, 9, 6]
>>> len(filtered_list)
3
>>> # compare to generator expression
... 
>>> filtered_gen = (item for item in my_list if item > 3)
>>> print filtered_gen  # notice it a generator object
<generator object at 0xb7d5e02c>
>>> len(filtered_gen) # So technically, it has no length
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'generator' has no len()
>>> # We extract each item out individually. We'll do it manually first.
... 
>>> filtered_gen.next()
5
>>> filtered_gen.next()
9
>>> filtered_gen.next()
6
>>> filtered_gen.next() # Should be all out of items and give an error
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> # Yup, the generator is spent. No values for you!
... 
>>> # Let prove it gives the same results as our list comprehension
... 
>>> filtered_gen = (item for item in my_list if item > 3)
>>> gen_to_list = list(filtered_gen)
>>> print gen_to_list
[5, 9, 6]
>>> filtered_list == gen_to_list
True
>>> 

Поскольку выражение генератора должно давать только один элемент за раз, это может привести к большой экономии в использовании памяти. Выражения генератора наиболее важны в сценариях, где вам нужно брать по одному элементу за раз, выполнять множество вычислений на основе этого элемента, а затем перейти к следующему элементу. Если вам нужно больше одного значения, вы также можете использовать выражение генератора и захватить несколько за раз. Если вам нужны все значения до того, как ваша программа продолжит работу, используйте вместо этого список.

Ответ 2

Понимание генератора - это ленивая версия понимания списка.

Это похоже на понимание списка, за исключением того, что он возвращает итератор вместо списка, т.е. объект со следующим() методом, который даст следующий элемент.

Если вы не знакомы со списками, см. здесь и для генераторов см. .

Ответ 3

Пояснение List/generator - это конструкция, которую вы можете использовать для создания нового списка/генератора из существующего.

Предположим, вы хотите сгенерировать список квадратов каждого числа от 1 до 10. Вы можете сделать это в Python:

>>> [x**2 for x in range(1,11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

здесь range(1,11) генерирует список [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], но функция range не является генератором перед Python 3.0, и поэтому используемая мной конструкция является пониманием списка.

Если бы я хотел создать генератор, который делает то же самое, я мог бы сделать это следующим образом:

>>> (x**2 for x in xrange(1,11))
<generator object at 0x7f0a79273488>

Однако в Python 3 range является генератором, поэтому результат зависит только от используемого вами синтаксиса (квадратные скобки или круглые скобки).

Ответ 4

Понимание генератора - это простой способ создания генераторов с определенной структурой. Допустим, вам нужен generator, который выводит по одному все четные числа в your_list. Если вы создадите его с помощью стиля функции, это будет следующим:

def allEvens( L ):
    for number in L:
        if number % 2 is 0:
            yield number

evens = allEvens( yourList )

Вы можете добиться того же результата с помощью выражения для выражения выражения:

evens = ( number for number in your_list if number % 2 == 0 )

В обоих случаях, когда вы вызываете next(evens), вы получаете следующее четное число в your_list.

Ответ 5

Понимание генератора - это подход к созданию итераций, что-то вроде курсора, который перемещается по ресурсу. Если вы знаете курсор mysql или курсор mongodb, вы можете знать, что все фактические данные никогда не загружаются в память сразу, а по одному. Курсор перемещается вперед и назад, но в памяти всегда есть элемент с одной строкой/списком.

Короче говоря, используя понимание генераторов, вы можете легко создавать курсоры в python.

Ответ 6

Еще один пример понимания генератора:

print 'Generator comprehensions'

def sq_num(n):
    for num in (x**2 for x in range(n)):    
        yield num

for x in sq_num(10):
    print x