Как именно работает понимание генератора? - PullRequest
77 голосов
/ 13 декабря 2008

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

Ответы [ 6 ]

123 голосов
/ 13 декабря 2008

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

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() на __next__()

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

16 голосов
/ 13 декабря 2008

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

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

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

4 голосов
/ 13 декабря 2008

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

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

2 голосов
/ 29 декабря 2013

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

0 голосов
/ 24 августа 2017

Другой пример понимания генератора:

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 
0 голосов
/ 12 декабря 2014

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...