Понимание Python потрясающе! | Кодементор

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

Основные понимания списков

Итак, давайте создадим простой сценарий, в котором мы можем захотеть выполнить итерацию по списку, чтобы создать новый список.

numbers = [1, 2, 3, 4, 5]
doubled = []

for number in numbers:
  doubled.append(number * 2)

Достаточно просто. Мы берем каждое число по одному, а затем удваиваем это число, добавляя его в новый список с именем doubled.

Чтобы было ясно, этот код полностью функционален, и его синтаксис в порядке. Однако мы можем написать такой шаблон намного короче, не жертвуя читабельностью. Звучит хорошо, верно?

Введите понимание списка:

numbers = [1, 2, 3, 4, 5]
doubled = [number * 2 for number in numbers]

Вот и все. Просто найдите минутку и полюбуйтесь, насколько это лаконично и читабельно. Это действительно одна из моих любимых частей синтаксиса Python.

Структура понимания списка выглядит следующим образом:

new_list = [ <value to append> <for loop definition> ]

Поскольку вторая половина понимания — это просто определения цикла for, к которым мы все привыкли писать, синтаксис понимания должен даваться вам очень легко. Как и в случае с циклами for, мы можем перебирать любой итерируемый объект: это не обязательно должен быть список.

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

Увлекайтесь условными предложениями

Итак, что произойдет, если у нас есть некоторая условная логика внутри нашего цикла for, и мы добавляем только некоторые значения в этот новый список. Это довольно распространенный вариант использования, поэтому можем ли мы разобраться с этим внутри понимания? Абсолютно!

Давайте рассмотрим новый пример, в котором у нас есть список имен, и мы хотим создать новый список, содержащий только имена, оканчивающиеся на «n».

names = ["Anne", "Paul", "Martin", "Helen", "Jake", "Alan", "Sarah"]
final_n_names = []

for name in names:
  if name.endswith("n"):
    final_n_names.append(name)

Если вы не знакомы с endswith метод, он просто возвращает True или же False в зависимости от того, соответствует ли данная строка суффиксу, указанному в качестве аргумента.

Опять же, у нас есть совершенно функциональный код, но он также немного более многословен, чем нам действительно нужно. Вместо этого мы снова можем использовать понимание.

names = ["Anne", "Paul", "Martin", "Helen", "Jake", "Alan", "Sarah"]
final_n_names = [name for name in names if name.endswith("n")]

Как видите, условие просто добавлено в конец нашего определения цикла for. Поэтому мы можем обновить наш синтаксис понимания, чтобы он выглядел следующим образом:

new_list = [ <value to append> <for loop definition> <filtering conditions> ]

Несколько условий

Читатели с орлиным взглядом могли заметить, что я написал условие фильтрациис во множественном числе. Это потому, что мы можем указать столько условий, сколько захотим. Мы можем либо объединить серию операторов if, либо использовать логические операторы, такие как and & or делать сложные условия.

Небо твой предел! Только не делайте это слишком сложным, потому что читать может быть трудно. Если ваше понимание становится слишком длинным, вы, вероятно, захотите вместо этого использовать цикл for.

Читабельность — это главное!

Условия сначала

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

В итоге мы добавляем логическое значение!

names = ["Anne", "Paul", "Martin", "Helen", "Jake", "Alan", "Sarah"]
final_n_names = [name.endswith("n") for name in names]


Наверное, не совсем то, что мы хотели.

Несколько циклов в одном понимании

Точно так же, как мы не ограничены одним оператором if внутри понимания, мы также можем использовать несколько определений циклов. Будьте осторожны с этим, потому что это может быстро стать трудным для анализа, но все же полезно знать об этом.

Например, мы можем указать пару циклов внутри включения, чтобы сгенерировать все возможные комбинации бросков для двух шестигранных игральных костей:

roll_combos = [(d1, d2) for d1 in range(1, 7) for d2 in range(1, 7)]

В этом понимании элементы в нашем окончательном списке на самом деле все кортежи. Как видите, мы добавляем (d1, d2) в новый список для каждой итерации циклов.

Вывод строки выше выглядит следующим образом:

[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2,6), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), (4, 1), (4, 2), (4, 3), (4, 4), (4, 5), (4, 6), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5), (5, 6), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6)]

Неплохо для одной строки кода.

Различные типы понимания

Установить понимание

Понимание списков прекрасно, но это не единственный вид понимания, который у нас есть. Например, вместо этого мы можем выполнить комплексное понимание. Синтаксис абсолютно идентичен: мы просто заключаем понимание в фигурные скобки. {} вместо квадратных скобок [].

numbers = [1, 2, 3, 4, 5]
doubled = {number * 2 for number in numbers}

Результатом понимания множества является, как вы можете себе представить, множество.

Словарные понимания

Другой менее распространенный тип понимания — это понимание по словарю.

Словарные включения выглядят как множества, за исключением того, что мы предоставляем ключ и значение в качестве «добавляемого значения». Вы, вероятно, увидите понимание словаря в сочетании с zipно если вам не нужно выполнять некоторые изменения ключей и значений, вам лучше использовать dict вместо этого конструктор.

Конечно, нам не нужно использовать zipи мы можем создать понимание словаря, перебирая простой список.

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

names = ["Anne", "Paul", "Martin", "Helen"]
name_dict = {name.lower(): len(name) for name in names}

# {'anne': 4, 'paul': 4, 'martin': 6, 'helen': 5}

Опять же, словарное понимание является гораздо более нишевым, чем что-то вроде понимания списка, но это все же ценный инструмент, о котором нужно знать. Они могут быть именно тем, что вам нужно для данной проблемы.

Подведение итогов

Надеюсь, теперь вы рады использовать включения в свой собственный код! Это действительно одна из моих любимых вещей в Python, и они так много делают для сокращения шаблонного кода. Очень часто они также становятся более читабельными!

Только не увлекайся. Иногда нам нужен старый добрый цикл for, особенно когда мы выполняем сложную логику. Держите просто. Держите его читабельным.

До скорого!

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *