Выражение-генератор - это выражение, которое возвращает итератор, которые более удобны для памяти (потребляют меньше памяти).
Некоторые простые генераторы могут быть лаконично закодированы в виде выражений с использованием синтаксиса, аналогичного списка-выражения, но с круглыми скобками вместо квадратных скобок. Эти выражения предназначены для ситуаций, когда генератор сразу же используется функцией.
>>> (i*i for i in range(5))
# <generator object <genexpr> at 0x7f2ee9b47d10>
Выражения генераторы более компактны, но менее универсальны, чем полные генераторные определения и, как правило, более удобны для памяти, чем эквивалентные списки. Обратите внимание, если обрабатывается большая структура данных без использования генератора, то она сразу вся загружается в память, что займет значительную часть памяти, а в некоторых случаях оперативной памяти может не хватить и тогда приложение будет вызывать исключение MemoryError
. В случае использования выражения-генератора, такого не происходит, так как элементы создаются и будут обрабатываться по-одному.
Выражения-генераторы нельзя писать без скобок - это синтаксическая ошибка;
>>> i*i for i in range(10) # File "<stdin>", line 1 # i*i for i in range(10) # ^ # SyntaxError: invalid syntax
При передаче в функцию дополнительные скобки необязательны;
# сумма квадратов >>> sum(i*i for i in range(10)) # 285
Выражения-генераторы не поддерживают получение длины функцией len()
;
>>> len(i*i for i in range(10)) # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # TypeError: object of type 'generator' has no len()
Выражения-генераторы не поддерживают получение элемента по индексу;
>>> gen = (i*i for i in range(10)) >>> gen[1] # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # TypeError: 'generator' object is not subscriptable
К выражению-генератору нельзя применить обычные операции среза или функцию slice()
. Для этих целей, можно воспользоваться функцией itertools.islice()
модуля itertools
.
>>> gen = (i*i for i in range(10)) >>> gen[1:5] # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # TypeError: 'generator' object is not subscriptable >>> import itertools >>> list(itertools.islice(gen, 1, 5)) # [1, 4, 9, 16]
После использования/итерации по выражению-генератору, оно остается пустым;
>>> gen = (i*i for i in range(10)) >>> list(gen) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> list(gen) # []
>>> xvec = [10, 20, 30] >>> yvec = [7, 5, 3] #скалярное произведение >>> sum(x*y for x,y in zip(xvec, yvec)) # 260 # Согласно PEP8 - то что в скобках, то можно переносить # следовательно выражение-генератор можно записать # так, что бы было удобно его читать >>> unique_words = set( word for line in page for word in line.split() ) # и еще пример >>> valedictorian = max( (student.gpa, student.name) for student in graduates ) # перевернем слово >>> data = 'golf' >>> drow = ( ... data[i] ... for i in range(len(data) - 1, -1, -1) ... ) >>> list(drow) # ['f', 'l', 'o', 'g']