Шаг 19.
Однострочники Python.Трюки Python. Поиск самых высокооплачиваемых работников с помощью спискового включения. Общее описание

    На этом шаге мы познакомся с прекрасной, очень эффективной и полезной возможностью Python для создания списков: списковым включением (list comprehension).

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


employees = {'Alice': 100000,
             'Bob': 99817,
             'Carol': 122908,
             'Frank': 88123,
             'Eve': 93121}
top_earners = []
for key, val in employees.items():
    if val >= 100000:
        top_earners.append((key, val))
Архив с файлом можно взять здесь.

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

    В Python существует замечательный способ создания новых списков: списковое включение. Оно описывается простой формулой:

  [выражение + контекст] 

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

  [х * 2 for х in range(3)]

    Выделенная жирным шрифтом часть, for х in range(3), представляет собой контекст, а остальная часть, х * 2, - выражение. Выражение удваивает значения 0, 1, 2, сгенерированные контекстом. Таким образом, результат спискового включения представляет собой следующий список:

  [0, 2, 4]

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

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

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

  print([(1)x (2)for х in range(5)])
  # [0, 1, 2, 3, 4]

    Выражение (1): тождественная функция (не меняет контекст переменной x).

    Контекст (2): переменная контекста x принимает все значения, возвращаемые функцией range(): 0, 1, 2, 3, 4.

  print([(1)(x, y) (2)for x in range(3) for y in range(3)])
  # [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

    Выражение (1): создает новый кортеж из переменных контекста x и y.

    Контекст (2): переменная контекста x проходит в цикле по всем значениям, возвращаемым функцией range (0, 1, 2); то же делает и переменная контекста y. Эти два цикла for - вложенные, вследствие чего переменная контекста у повторяет итерации своего цикла для каждого из значений переменной контекста х. Таким образом, получается 3 * 3 = 9 сочетаний переменных контекста.

  print([(1)x ** 2 (2)for х in range(10) if x % 2 > 0])
  # [1, 9, 25, 49, 81]

    Выражение (1): функция возведения в квадрат переменной контекста x.

    Контекст (2): переменная контекста x проходит в цикле по всем значениям, возвращаемым функцией range() - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - но только нечетным, то есть когда x % 2 > 0.

  print([(1)x.lower() (2)for x in ['I', 'AM', 'NOT', 'SHOUTING']])
  # ['i', 'am', 'not', 'shouting']

    Выражение (1): строковая функция приведения к нижнему регистру переменной контекста x.

    Контекст (2): переменная контекста x проходит в цикле по всем строковым значениям в списке: 'I', 'AM', 'NOT', 'SHOUTING'.

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

    На следующем шаге мы закончим изучение этого вопроса.




Предыдущий шаг Содержание Следующий шаг