Когда вы должны использовать выражения генератора и когда вы должны использовать списочные выражения в Python?
# Generator expression
(x*2 for x in range(256))
# List comprehension
[x*2 for x in range(256)]
python
list-comprehension
generator
Readonly
источник
источник
[exp for x in iter]
быть просто сахар дляlist((exp for x in iter))
? или есть разница в исполнении?X = [x**2 for x in range(5)]; print x
сY = list(y**2 for y in range(5)); print y
, второе выдаст ошибку. В Python3 понимание списка действительно является синтаксическим сахаром для выражения генератора, переданного,list()
как вы ожидали, поэтому переменная цикла больше не будет просачиваться .Ответы:
Хороший ответ Джона (этот список лучше, если вы хотите повторять что-то несколько раз). Однако также стоит отметить, что вы должны использовать список, если вы хотите использовать любой из методов списка. Например, следующий код не будет работать:
В основном, используйте выражение генератора, если все, что вы делаете, это итерация один раз. Если вы хотите сохранить и использовать сгенерированные результаты, то вам, вероятно, лучше понять список.
Поскольку производительность является наиболее распространенной причиной выбора одного над другим, я советую не беспокоиться об этом и просто выбрать один; если вы обнаружите, что ваша программа работает слишком медленно, тогда и только тогда вам следует вернуться и заняться настройкой своего кода.
источник
a = [1, 2, 3] b = [4, 5, 6] a.extend(b)
- теперь будет a [1, 2, 3, 4, 5, 6]. (Можете ли вы добавить новые строки в комментариях ??)a = (x for x in range(0,10)), b = [1,2,3]
например.a.extend(b)
бросает исключение.b.extend(a)
оценит все, в этом случае нет смысла делать его генератором.Итерация по выражению генератора или пониманию списка будет делать то же самое. Однако понимание списка сначала создаст весь список в памяти, в то время как выражение генератора будет создавать элементы на лету, так что вы сможете использовать его для очень больших (а также бесконечных!) Последовательностей.
источник
itertools.count(n)
это бесконечная последовательность целых чисел, начиная с n, поэтому(2 ** item for item in itertools.count(n))
будет бесконечной последовательностью степеней,2
начиная с2 ** n
.Используйте списки, когда результат должен повторяться несколько раз или когда скорость имеет первостепенное значение. Используйте выражения генератора, где диапазон большой или бесконечный.
Посмотрите выражения Генератора и список понятий для получения дополнительной информации.
источник
lists
быстрее, чемgenerator
выражения? Прочитав ответ Д.Ф., выяснилось, что все наоборот.Важным моментом является то, что понимание списка создает новый список. Генератор создает итеративный объект, который будет «фильтровать» исходный материал на лету, когда вы используете биты.
Представьте, что у вас есть файл журнала объемом 2 ТБ, называемый "принц", и вам нужно содержимое и длина для всех строк, начинающихся со слова "ВХОД".
Итак, попробуйте начать с написания списка:
Это затирает весь файл, обрабатывает каждую строку и сохраняет совпадающие строки в вашем массиве. Следовательно, этот массив может содержать до 2 ТБ контента. Это много оперативной памяти, и, вероятно, не практично для ваших целей.
Поэтому вместо этого мы можем использовать генератор, чтобы применить «фильтр» к нашему контенту. На самом деле данные не читаются, пока мы не начнем итерацию по результату.
Из нашего файла еще не было прочитано ни одной строки. На самом деле, скажем, мы хотим отфильтровать наш результат еще дальше:
Пока ничего не прочитано, но мы указали два генератора, которые будут работать с нашими данными так, как мы хотим.
Давайте запишем наши отфильтрованные строки в другой файл:
Теперь мы читаем входной файл. Поскольку наш
for
цикл продолжает запрашивать дополнительные строки,long_entries
генератор запрашивает строки изentry_lines
генератора, возвращая только те, длина которых превышает 80 символов. И, в свою очередь,entry_lines
генератор запрашивает строки (отфильтрованные как указано) отlogfile
итератора, который, в свою очередь, читает файл.Таким образом, вместо того, чтобы «выталкивать» данные в вашу функцию вывода в виде полностью заполненного списка, вы даете функции вывода способ «извлекать» данные только тогда, когда это необходимо. В нашем случае это гораздо эффективнее, но не так гибко. Генераторы один путь, один проход; данные из файла журнала, который мы прочитали, немедленно удаляются, поэтому мы не можем вернуться к предыдущей строке. С другой стороны, нам не нужно беспокоиться о сохранении данных, как только мы закончим с ними.
источник
Преимущество выражения генератора заключается в том, что оно использует меньше памяти, поскольку не создает весь список сразу. Выражения генератора лучше всего использовать, когда список является посредником, например, суммируя результаты или создавая из результатов выборку.
Например:
Преимущество состоит в том, что список генерируется не полностью, и поэтому используется мало памяти (и также должно быть быстрее)
Тем не менее, вы должны использовать списки, когда желаемый конечный продукт является списком. Вы не собираетесь сохранять какую-либо память, используя выражения генератора, так как вам нужен сгенерированный список. Вы также получаете возможность использовать любые функции списка, например отсортированные или обратные.
Например:
источник
sum(x*2 for x in xrange(256))
sorted
иreversed
отлично работает с любыми повторяемыми выражениями-генераторами.При создании генератора из изменяемого объекта (например, списка) следует помнить, что генератор будет оцениваться по состоянию списка во время использования генератора, а не во время создания генератора:
Если есть вероятность, что ваш список будет изменен (или изменяемый объект внутри этого списка), но вам нужно состояние при создании генератора, вам нужно вместо этого использовать понимание списка.
источник
Иногда вы можете избежать использования функции tee из itertools , она возвращает несколько итераторов для одного и того же генератора, который можно использовать независимо.
источник
Я использую модуль Hadoop Mincemeat . Я думаю, что это отличный пример, чтобы принять к сведению:
Здесь генератор извлекает числа из текстового файла (размером до 15 ГБ) и применяет к этим числам простую математику, используя Hadoop map-Reduce. Если бы я не использовал функцию yield, а вместо понимания списка, вычисление сумм и среднего потребовало бы намного больше времени (не говоря уже о сложности пространства).
Hadoop - отличный пример использования всех преимуществ Генераторов.
источник