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

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

13.12.2008 03:55:44
Чтобы быть ясным, имя языка для них - выражения генератора , а не понимания генератора .
ShadowRanger 3.04.2018 21:23:31
@ShadowRanger В июле 2018 года обсуждается список рассылки Python-dev на тему «Синтаксис понимания имен», где существует предварительное, но довольно единодушное согласие называть их «генераторами понимания» для согласованности.
Aaron Hall♦ 6.12.2018 16:30:31
6 ОТВЕТОВ
РЕШЕНИЕ

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

>>> 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 <genexpr> at 0x7f2ad75f89e0>
>>> 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.
... 
>>> next(filtered_gen)
5
>>> next(filtered_gen)
9
>>> next(filtered_gen)
6
>>> next(filtered_gen) # 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
>>> 

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

137
24.12.2019 20:32:02
Один вопрос здесь. Я использовал next (gen_name), чтобы получить результат, и он работал в Python 3. Есть ли какой-то конкретный сценарий, где нам нужно использовать __next __ ()?
Ankit Vashistha 30.05.2018 06:12:28
@AnkitVashistha Нет, всегда используйте next(...)вместо .__next__()Python 3.
Todd Sewell 14.08.2018 12:18:07
@gotgenes @AnkitVashistha If you need more than one value, you can also use a generator expression and grab a few at a time. Не могли бы вы привести пример об этом использовании? Спасибо.
LittleZero 10.09.2018 04:12:34

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

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

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

19
13.12.2008 04:19:40

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

Допустим, вы хотите сгенерировать список квадратов каждого числа от 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
13.12.2008 04:14:48
Это не верно. То, является ли внешнее выражение генератором, не имеет никакого отношения к тому, является ли внутреннее выражение. Хотя очевидно, что в выражении-генераторе, извлекающем элементы из списка, обычно нет особого смысла, это можно сделать.
Antimony 5.03.2013 23:46:37
Можно ли это переписать более четко? Я понимаю, что вы говорите, но, как говорит Сурьма, похоже, вы говорите что-то еще. (и похоже, что вы говорите, что это неправильно)
Lyndon White 17.01.2014 02:36:31

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

2
28.12.2013 23:06:29

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

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

0
12.12.2014 14:42:21

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

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 
-1
24.08.2017 15:44:31