При программировании довольно часто возникает желание создать какую-то коллекцию из другой коллекции, обычно с некоторыми изменениями, происходящими по пути. Python предоставляет потрясающий набор инструментов для решения такого рода проблем: понимание. Если вы не используете понимание регулярно в своем коде, читайте дальше, и я покажу вам, что вы упускаете!
Основные сведения о списке
Итак, давайте создадим простой сценарий, в котором мы, возможно, захотим повторить список, чтобы создать новый список.
numbers = [1, 2, 3, 4, 5] doubled = [] for number in numbers: doubled.append(number * 2)
Достаточно просто. Мы берем каждый номер по одному, а затем удваиваем это число, добавляя его в новый список под названием удвоенный
.
Чтобы быть ясным, этот код полностью функциональен, и синтаксис в порядке. Однако мы можем написать такой шаблон гораздо короче, не жертвуя удобочитаемостью. Звучит неплохо, правда?
Введите список понятий:
numbers = [1, 2, 3, 4, 5] doubled = [number * 2 for number in numbers]
Это действительно все, что нужно. Просто найдите минутку и полюбуйтесь, насколько это лаконично и читабельно. Это действительно одна из моих любимых частей синтаксиса Python.
Структура понимания списка выглядит следующим образом:
new_list = []
Поскольку вторая половина понимания-это просто определения цикла 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 = []
Несколько условий
Зоркие читатели, возможно, заметили, что я написал условие фильтрации s во множественном числе. Это происходит потому, что мы действительно можем указать столько условий, сколько захотим. Мы можем либо связать вместе ряд операторов if, либо использовать булевы операторы, такие как и
& или
, для создания сложных условий.
Небо – твой предел! Только не делайте это слишком сложным, потому что вещи могут стать трудными для чтения. Если ваше понимание становится слишком длинным, вы, вероятно, захотите вместо этого использовать цикл for.
Читабельность-это король!
Сначала условия
Мы также можем написать условное утверждение в начале понимания, но это означает нечто совсем другое. Помните, что первое, что мы понимаем в нашем списке, – это значение, которое нужно добавить в наш новый список, поэтому, если мы используем здесь условие, что произойдет?
В конечном итоге мы добавляем логическое значение!
names = ["Anne", "Paul", "Martin", "Helen", "Jake", "Alan", "Sarah"] final_n_names = [name.endswith("n") for name in names] # [False, False, True, True, False, True, False]
Вероятно, не совсем то, что мы хотели.
Несколько циклов в одном понимании
Точно так же, как мы не ограничены одним оператором 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
, но если вам не нужно вносить некоторые изменения в ключи и значения, вам лучше использовать вместо этого конструктор dictionary
.
Конечно, нам не нужно использовать 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, особенно когда мы выполняем сложную логику. Держать просто. Держите его читаемым.
До следующего раза!