8 быстрых советов по рефакторингу Python для более чистого и более Pythonic-кода.
В этом уроке рассмотрим 8 быстрых советов по рефакторингу кода Python для более чистого и более питоновского кода.
1: объединить вложенные операторы if
Давайте начнем довольно просто. Вместо вложенных операторов if, подобных этому, просто объедините их в один.
if a: if b: pass # -> refactor if a and b: pass
2: Используйте любой вместо цикла
Здесь мы хотим проверить, есть ли в списке хотя бы один положительный элемент. Более длинное решение состоит в том, чтобы перебрать все числа, проверить текущее число, а затем прервать, как только условие станет истинным. Но для этой задачи в Python существует специальный метод any function . Any возвращает True, если любой элемент итерации имеет значение true. Это намного короче и более питонично, чем зацикливание вручную.
numbers = [-1, -2, -4, 0, 3, -7] has_positives = False for n in numbers: if n > 0: has_positives = True break # -> refactor has_positives = any(n > 0 for n in numbers)
3. Вытащите операторы из циклов for/while
Много раз вы видите циклы, в которых переменная определена внутри цикла, но она никогда не изменяется. Это ненужные операции, поэтому просто вытащите его из цикла, и тогда вам нужно будет создать его только один раз.
for building in buildings:
city = 'London'
addresses.append(building.street_address, city)
# -> refactor
city = 'London'
for building in buildings:
addresses.append(building.street_address, city)
4. Удалите встроенные переменные, которые используются только один раз и немедленно возвращаются
Много раз вы видите код, в котором переменная определяется внутри функции в конце, а через одну строку она немедленно возвращается. Если понятно, что делает функция, просто верните результат напрямую. Это более лаконично и позволяет избежать ненужной переменной. Тем не менее, иногда это может быть полезно, если не совсем ясно, что делает функция, и тогда вы можете дать своей последней переменной осмысленное имя и использовать ее как самодокументирующийся код.
def state_attributes(self): """Return the state attributes.""" state_attr = { ATTR_CODE_FORMAT: self.code_format, ATTR_CHANGED_BY: self.changed_by, } return state_attr # -> refactor def state_attributes(self): """Return the state attributes.""" return { ATTR_CODE_FORMAT: self.code_format, ATTR_CHANGED_BY: self.changed_by, }
5: Замените оператор if выражением if
Вместо того, чтобы использовать оператор if else для установки значения переменной, вы можете просто установить это в одной строке с выражением if, например. Однако этот метод рефакторинга немного спорен. Некоторые люди по-прежнему предпочитают первый вариант, и это нормально.
if condition: x = 1 else: x = 2 # -> refactor x = 1 if condition else 2
6: Добавьте защитную оговорку
Глядя на этот код, трудно быстро понять, что происходит. Есть несколько операторов if-else и несколько отступов. Присмотревшись поближе, вы можете заметить, что первый оператор if покрывает почти весь код функции, только в конце у нас есть соответствующее предложение else, где мы просто возвращаем False.
Мы можем взять это предложение else и переместить его в самое начало. Это также известно как оператор защиты . Поэтому, если условие неверно, мы не выполняем остальную часть кода функции. Таким образом, wet избавился от одного предложения else, и теперь во всем коде на один уровень отступа меньше. Это выглядит намного чище и легче для понимания.
def should_i_wear_this_hat(self, hat):
if isinstance(hat, Hat):
current_fashion = get_fashion()
weather_outside = self.look_out_of_window()
is_stylish = self.evaluate_style(hat, current_fashion)
if weather_outside.is_raining:
print("Damn.")
return True
else:
print("Great.")
return is_stylish
else:
return False
# -> refactor
def should_i_wear_this_hat(self, hat):
if not isinstance(hat, Hat):
return False
current_fashion = get_fashion()
weather_outside = self.look_out_of_window()
is_stylish = self.evaluate_style(hat, current_fashion)
if weather_outside.is_raining:
print("Damn.")
return True
else:
print("Great.")
return is_stylish
7. Переместите задания ближе к месту их использования
Это улучшенный код из последнего примера, но все еще требуется несколько секунд, чтобы понять, что здесь происходит. Итак, мы хотим проверить, должны ли мы носить шляпу или нет. Логика такова: если идет дождь, мы всегда говорим True, а если дождя нет, мы говорим True, если шляпа стильная. Один из простых способов радикально улучшить читабельность этой логики — приблизить присваивания к месту ее использования. Давайте получим погоду прямо перед использованием оператора if. И теперь переменные fashion и style нужны только в предложении else, так что переместите их вниз. Теперь должно быть намного яснее, что происходит.
Помните совет №4? Мы могли бы еще больше сократить код и немедленно вернуть результат оценки стиля. Однако в этом примере мне также нравится имя is_stylish, потому что оно позволяет вам знать, что если шляпа стильная, вы говорите True, а в противном случае — False. Так что здесь можно оставить дополнительную переменную.
def should_i_wear_this_hat(self, hat): if not isinstance(hat, Hat): return False current_fashion = get_fashion() weather_outside = self.look_out_of_window() is_stylish = self.evaluate_style(hat, current_fashion) if weather_outside.is_raining: print("Damn.") return True else: print("Great.") return is_stylish # -> refactor def should_i_wear_this_hat(self, hat): if not isinstance(hat, Hat): return False weather_outside = self.look_out_of_window() if weather_outside.is_raining: print("Damn.") return True else: print("Great.") current_fashion = get_fashion() return self.evaluate_style(hat, current_fashion) # is_stylish = self.evaluate_style(hat, current_fashion) # return is_stylish
8. Упростите проверку последовательности
Когда вам нужно проверить, есть ли элементы в коллекции, например в списке, вам не нужно писать if len(your_list) > 0
. Можно просто сказать if your_list
. Это рекомендованный pep 8 способ, также известный как проверка достоверности . Это возможно, потому что в Python пустые последовательности и коллекции оцениваются как False. Так что это можно применить к строкам, кортежам, спискам, словарям и множествам.
if len(list_of_hats) > 0: hat_to_wear = choose_hat(list_of_hats) # -> refactor if list_of_hats: hat_to_wear = choose_hat(list_of_hats)