4 простых способа рефакторинга кода


Рефакторинг — это процесс обновления существующего кода без изменения его функционала. Существует множество причин рефакторить код, включая производительность, читаемость и масштабируемость в будущем.

Рефакторинг — это важная часть процесса для любого кодера, не только для продвинутых разработчиков. Для менее опытной аудитории рефакторинг является прекрасной возможностью изучать и отрабатывать новые приёмы, повышать свой уровень от сделано до сделано правильно!

Рассмотрим пять простых способов рефакторинга кода для начинающих в Python с пояснениями преимуществ и демонстрацией кода до и после.

Определение функций для повторяющихся задач

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

Функции предоставляют множество преимуществ, но с точки зрения рефакторинга сокращается объём кода, улучшается читаемость. Кроме того, если нужно обновить задачу, делать это понадобится только на одном участке — в определении функции.

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

До while True: length = int(input("Enter the length: ")) if length > 0: break while True: width = int(input("Enter the width: ")) if length > 0: break print("The area is", length * width)

Заметьте, что два блока почти идентичны. А что, если понадобится вычислить объём куба? Скорее всего мы скопируем цикл while, изменив имя переменной и приглашение к вводу.

После def input_positive_integer(prompt): while True: input_value = int(input(prompt)) if input_value > 0: return input_value length = input_positive_integer("Enter the length: ") width = input_positive_integer("Enter the width: ") print("The area is", length * width)

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

Конструктор списков вместо цикла for

Конструктор списков — один из самых легендарных конструкторов Python. Конструктор списков является более чистой и быстрой реализацией в сравнении с многими простыми циклами for.

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

Давайте рассмотрим два примера, один простой и второй немного посложнее.

В первом примере выберем нечётные числа из списка целых чисел.

До my_numbers = [1,2,3,4,5] odd_numbers = [] for item in my_numbers: if item % 2 == 1: odd_numbers.append(item) print(odd_numbers) # [1, 3, 5]

В этом примере запустим цикл в 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 для фильтрации.

Можно создавать более сложные конструкторы списков, что даёт большие преимущества. Во втором примере предположим, что у нас есть двумерная матрица целых чисел и каждое значение мы хотим возвести в квадрат.

До matrix = [[1,2,3],[4,5,6],[7,8,9]] squared_matrix = [] for row in matrix: line = [] for item in row: line.append(item ** 2) squared_matrix.append(line) print(squared_matrix) # [[1, 4, 9], [16, 25, 36], [49, 64, 81]]

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

После рефакторинга matrix = [[1,2,3],[4,5,6],[7,8,9]] squared_matrix = [ [ item ** 2 for item in row ] for row in matrix ] print(squared_matrix) # [[1, 4, 9], [16, 25, 36], [49, 64, 81]]

Здесь немного расширено описание для лучшей читаемости, но все вычисления и вложенный цикл 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(): перебор будет производиться по фактическому списку, и независимая переменная будет не нужна.

До races = ["Terran", "Protoss", "Zerg"] for i in range(len(races)): print(i+1, races[i]) # 1 Terran # 2 Protoss # 3 Zerg

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

После рефакторинга races = ["Terran", "Protoss", "Zerg"] for i, race in enumerate(races, 1): print(i, race) # 1 Terran # 2 Protoss # 3 Zerg

Функция enumerate() принимает два аргумента: итерируемое и начальное значение счёта, а возвращает текущее порядковое значение и элемент в итерируемом. Примечание: временная переменная счёта идёт первой в цикле for, а начальное значение счёта идёт вторым в вызове функции. Это распространённая ошибка. 

Возьмите за правило пересматривать и рефакторить свой код. Ваша разработка будет медленнее без актуальных навыков и оптимизированных методов программирования. 


Перевод статьи Jonathan Hsu: 4 Simple Ways to Refactor Your Python Code


Поделиться статьей:


Вернуться к статьям

Комментарии

    Ничего не найдено.