0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Словари и множества полезны лишь тогда, когда обладают полнотой информации об элементах. Это логично: если само множество или словарь не достроены до конца, то мы не можем проверить наличие значения в множестве или ключа в словаре другими способами.</p>
1
<p>Словари и множества полезны лишь тогда, когда обладают полнотой информации об элементах. Это логично: если само множество или словарь не достроены до конца, то мы не можем проверить наличие значения в множестве или ключа в словаре другими способами.</p>
2
<p>Со списками ситуация иная. Список - это последовательность элементов, поэтому его нужно обойти ровно один раз. А иногда даже не требуется доходить до конца списка - например, если мы ищем один конкретный элемент. Тут важно вспомнить, что map и filter не порождают списки сами по себе, а вместо этого порождают новые итераторы на основе итераторов-аргументов.</p>
2
<p>Со списками ситуация иная. Список - это последовательность элементов, поэтому его нужно обойти ровно один раз. А иногда даже не требуется доходить до конца списка - например, если мы ищем один конкретный элемент. Тут важно вспомнить, что map и filter не порождают списки сами по себе, а вместо этого порождают новые итераторы на основе итераторов-аргументов.</p>
3
<p>Конвейеры данных на основе итераторов получаются довольно эффективными, особенно в сочетании с функциями из модуля itertools. Так происходит потому, что никакая работа не выполняется, пока ее результат не понадобится принимающей стороне на выходе конвейера.</p>
3
<p>Конвейеры данных на основе итераторов получаются довольно эффективными, особенно в сочетании с функциями из модуля itertools. Так происходит потому, что никакая работа не выполняется, пока ее результат не понадобится принимающей стороне на выходе конвейера.</p>
4
<p>У генераторов списков есть еще одна важная особенность - весь список будет создан так или иначе, даже если от списка будут нужны не все элементы. Обычно выполнение цикла можно прервать с помощью break, но прервать вычисление генератора списков не получится. Кроме того, это будет выглядеть не декларативно. Впрочем, Python умеет использовать ленивость итераторов и в декларативном коде.</p>
4
<p>У генераторов списков есть еще одна важная особенность - весь список будет создан так или иначе, даже если от списка будут нужны не все элементы. Обычно выполнение цикла можно прервать с помощью break, но прервать вычисление генератора списков не получится. Кроме того, это будет выглядеть не декларативно. Впрочем, Python умеет использовать ленивость итераторов и в декларативном коде.</p>
5
<h2>Генераторные выражения</h2>
5
<h2>Генераторные выражения</h2>
6
<p>Выше мы говорили, что иногда последовательности не нужно вычислять целиком. Чтобы развить эту тему, добавим, что на самом деле получать и хранить законченные списки не нужно практически никогда.</p>
6
<p>Выше мы говорили, что иногда последовательности не нужно вычислять целиком. Чтобы развить эту тему, добавим, что на самом деле получать и хранить законченные списки не нужно практически никогда.</p>
7
<p>В тех редких случаях, когда нужен именно список, пригодятся генераторы списков. Но большинство задач решается с помощью<strong>генераторных выражений</strong>.</p>
7
<p>В тех редких случаях, когда нужен именно список, пригодятся генераторы списков. Но большинство задач решается с помощью<strong>генераторных выражений</strong>.</p>
8
<p>Выглядят они как генераторы списков. Разница только в круглых скобках вместо квадратных:</p>
8
<p>Выглядят они как генераторы списков. Разница только в круглых скобках вместо квадратных:</p>
9
<p>Как видите, результатом вычисления второго выражения является не список, а generator object - это<strong>объект-генератор</strong>. С его помощью мы откладываем вычисление элементов последовательности до появления необходимости в них.</p>
9
<p>Как видите, результатом вычисления второго выражения является не список, а generator object - это<strong>объект-генератор</strong>. С его помощью мы откладываем вычисление элементов последовательности до появления необходимости в них.</p>
10
<p>По сути объект-генератор - это итератор, поэтому его не получится обойти несколько раз:</p>
10
<p>По сути объект-генератор - это итератор, поэтому его не получится обойти несколько раз:</p>
11
<p>Здесь __iter__ вызывается для итератора каждый раз, но итератор возвращает самого себя вместо нового итератора. Вычисленные и использованные элементы нигде не сохраняются.</p>
11
<p>Здесь __iter__ вызывается для итератора каждый раз, но итератор возвращает самого себя вместо нового итератора. Вычисленные и использованные элементы нигде не сохраняются.</p>
12
<h2>Скобки нужны не всегда</h2>
12
<h2>Скобки нужны не всегда</h2>
13
<p>Часто можно встретить генераторное выражение в таком месте кода, где интерпретатор может однозначно понять, где границы этого выражения.</p>
13
<p>Часто можно встретить генераторное выражение в таком месте кода, где интерпретатор может однозначно понять, где границы этого выражения.</p>
14
<p>Самый частый пример - генераторное выражение в роли единственного аргумента функции:</p>
14
<p>Самый частый пример - генераторное выражение в роли единственного аргумента функции:</p>
15
<p>В подобных случаях скобки вокруг самого выражения можно опустить. Так же можно опускать скобки вокруг кортежа там, где это не мешает чтению кода.</p>
15
<p>В подобных случаях скобки вокруг самого выражения можно опустить. Так же можно опускать скобки вокруг кортежа там, где это не мешает чтению кода.</p>
16
<p>Такое избавление от лишних скобок часто делает код еще более лаконичным:</p>
16
<p>Такое избавление от лишних скобок часто делает код еще более лаконичным:</p>
17
<p>Этот код можно перевести так:</p>
17
<p>Этот код можно перевести так:</p>
18
<blockquote><p>Есть ли любой икс больше ста среди иксов в диапазоне от нуля до миллиона?</p>
18
<blockquote><p>Есть ли любой икс больше ста среди иксов в диапазоне от нуля до миллиона?</p>
19
</blockquote><p>Это выражение вычислится мгновенно, а числа будут проверяться по одному за раз.</p>
19
</blockquote><p>Это выражение вычислится мгновенно, а числа будут проверяться по одному за раз.</p>
20
<p>А теперь представим, что мы использовали any([… for …]). В таком случае Python тоже искал бы первое значение True в списке, но предварительно построил бы в памяти список в миллион элементов.</p>
20
<p>А теперь представим, что мы использовали any([… for …]). В таком случае Python тоже искал бы первое значение True в списке, но предварительно построил бы в памяти список в миллион элементов.</p>
21
<h2>Когда и что применять</h2>
21
<h2>Когда и что применять</h2>
22
<p>Старайтесь применять генераторные выражения везде, где это возможно. Использовать объекты-генераторы могут практически любые функции, которые работают с последовательностями в том или ином виде.</p>
22
<p>Старайтесь применять генераторные выражения везде, где это возможно. Использовать объекты-генераторы могут практически любые функции, которые работают с последовательностями в том или ином виде.</p>
23
<p>Даже при вызове функции для пачки аргументов лучше использовать генераторное выражение:</p>
23
<p>Даже при вызове функции для пачки аргументов лучше использовать генераторное выражение:</p>
24
<p>И уж тем более стоит использовать генераторные выражения посреди выражений с list, set и dict, а также среди генераторных выражений и конвейеров на основе map или filter.</p>
24
<p>И уж тем более стоит использовать генераторные выражения посреди выражений с list, set и dict, а также среди генераторных выражений и конвейеров на основе map или filter.</p>
25
<p>Раньше в Python существовали только генераторы списков и генераторные выражения. Множества и словари строили так:</p>
25
<p>Раньше в Python существовали только генераторы списков и генераторные выражения. Множества и словари строили так:</p>
26
<p>Здесь генераторное выражение создает элементы по одному за раз. Функции set() и dict() потребляют элементы итератора по одному, вставляя их в нужные места.</p>
26
<p>Здесь генераторное выражение создает элементы по одному за раз. Функции set() и dict() потребляют элементы итератора по одному, вставляя их в нужные места.</p>
27
<p>Это уже достаточно эффективный способ. Отдельные синтаксические конструкции для генераторов множеств и генераторы словарей мы использовали, чтобы повысить выразительность кода.</p>
27
<p>Это уже достаточно эффективный способ. Отдельные синтаксические конструкции для генераторов множеств и генераторы словарей мы использовали, чтобы повысить выразительность кода.</p>