Источник: Nuances of Programming
Рефакторинг — это процесс обновления существующего кода без изменения его функционала. Существует множество причин рефакторить код, включая производительность, читаемость и масштабируемость в будущем.
Рефакторинг — это важная часть процесса для любого кодера, не только для продвинутых разработчиков. Для менее опытной аудитории рефакторинг является прекрасной возможностью изучать и отрабатывать новые приёмы, повышать свой уровень от сделано до сделано правильно!
Рассмотрим пять простых способов рефакторинга кода для начинающих в Python с пояснениями преимуществ и демонстрацией кода до и после.
Определение функций для повторяющихся задач
Первый и, возможно, наиважнейший рефакторинг, который можно сделать, это определить функции для повторяющихся задач. Функция — это заданный набор операторов, выполняющихся с использованием имени функции, известного как вызов функции.
Функции предоставляют множество преимуществ, но с точки зрения рефакторинга сокращается объём кода, улучшается читаемость. Кроме того, если нужно обновить задачу, делать это понадобится только на одном участке — в определении функции.
Давайте рассмотрим пример, где нужно запросить длину и ширину прямоугольника для вычисления его площади.
До
Заметьте, что два блока почти идентичны. А что, если понадобится вычислить объём куба? Скорее всего мы скопируем цикл while, изменив имя переменной и приглашение к вводу.
После
Теперь код проще читать, кроме того мы сэкономили несколько строк кода. Что ещё лучше, в будущем можно будет легко использовать эту функцию и вставлять её в другой скрипт, экономя время.
Конструктор списков вместо цикла for
Конструктор списков — один из самых легендарных конструкторов Python. Конструктор списков является более чистой и быстрой реализацией в сравнении с многими простыми циклами for.
Существует множество преимуществ рефакторинга циклов for в конструкторы списков: код будет выполняться быстрее, существующие данные не будут меняться, кроме того, конструктор списков проще читать, как только вы к нему привыкаете.
Давайте рассмотрим два примера, один простой и второй немного посложнее.
В первом примере выберем нечётные числа из списка целых чисел.
До
В этом примере запустим цикл в my_numbers и используем оператор вычисления остатка, чтобы определить, нужно ли вставлять элемент в odd_numbers.
После рефакторинга
my_numbers = [1,2,3,4,5]
odd_numbers = [item for item in my_numbers if item % 2 == 1]
Подведём итог в этом примере: конструктор списков — это передача элементов в odd_numbers, перебор my_numbers, выполнение return (первый item) и применение оператора if для фильтрации.
Можно создавать более сложные конструкторы списков, что даёт большие преимущества. Во втором примере предположим, что у нас есть двумерная матрица целых чисел и каждое значение мы хотим возвести в квадрат.
До
Мы должны использовать вложенный цикл for вместе с временной переменной для хранения каждой строки перед вставкой в окончательную переменную.
После рефакторинга
Здесь немного расширено описание для лучшей читаемости, но все вычисления и вложенный цикл for обрабатываются в одном присвоении.
Логический оператор OR вместо условного оператора
Присвоение одного из двух значений может быть обработано с помощью простого оператора if:
if args['website']:
website = args['website']
else:
website = "https://nuancesprog.ru"
Эти типы присвоений “или-или” традиционно могут выполняться с помощью условного оператора, объединяющего присвоения в один.
До
website = args['website'] if args['website'] else "https://nuancesprog.ru"
Структура условного оператора такова:
value if true | expression | value if false
Когда выражение должно оценить, приводит ли “value-if-true” к булеву значению True, логический оператор OR может упростить трудно читаемый условный оператор.
После
website = args['website'] or "https://nuancesprog.ru"
Логический оператор OR пытается присвоить первое значение. Если первое значение приводит к False—None, пустая переменная и т.д.—используется второе значение.
Этот код значительно проще читать, он позволяет эффективно устанавливать значение по умолчанию при присвоении переменной.
Функция enumerate() вместо range()
Цикл for в Python может сбивать с толку, особенно, если вы привыкли работать с другими языками программирования. Вашим первым порывом будет создать индексную переменную и использовать её для перебора списка.
В результате часто используется функция range(). Этот приём не “в стиле” Python, в отличие от руководства по стилю и проверенных приёмов. Подробнее вы можете прочесть в моей статье “Перестаньте использовать range() в цикле for в Python”.
Если вам очень нужны индексы каждого значения, используйте функцию enumerate(): перебор будет производиться по фактическому списку, и независимая переменная будет не нужна.
До
Использование индекса в исходном списке приводит к неудачным методам, таким как обновление исходных значений, кроме того, читать код становится труднее… особенно в сложных вложенных структурах данных. Также мы вынуждены вручную управлять индексом, чтобы изменять значения порядковых номеров.
После рефакторинга
Функция enumerate() принимает два аргумента: итерируемое и начальное значение счёта, а возвращает текущее порядковое значение и элемент в итерируемом. Примечание: временная переменная счёта идёт первой в цикле for, а начальное значение счёта идёт вторым в вызове функции. Это распространённая ошибка.
Возьмите за правило пересматривать и рефакторить свой код. Ваша разработка будет медленнее без актуальных навыков и оптимизированных методов программирования.
Читайте также:
Читайте нас в телеграмме и vk
Перевод статьи Jonathan Hsu: 4 Simple Ways to Refactor Your Python Code