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


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

6 63

6 ответов:

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

версия python2:

>>> 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's 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's 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
>>> 

версия python3:

изменить next() to __next__()

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

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

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

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

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

Допустим, вы хотите создать список квадратов чисел от 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 является генератором, поэтому результат зависит только от используемого синтаксиса (квадратные скобки или круглые скобки).

понимание генератора-это простой способ создания генераторов с определенной структурой. Допустим, вы хотите 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.

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

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

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

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