HTML Diff
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>