We start simple. Don't nest if statements like this, just combine them into one.
if a: if b: pass # -> refactor if a and b: pas
Here we want to check if there is at least one positive element in the list. A longer solution is to loop through all numbers, check the current number, and then break when the condition is true. But for this task, there is a specialized method in Python, the any function. any returns True if any element of the iterable is true. This is much shorter and more pythonic than a manual loop.
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)
Many times you will see a variable defined in the loop, but it never changes. These are unnecessary operations, so pull it out of the loop and then you only have to create it once.
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)
Many times you will see code that defines a variable in the last function and one line later it returns immediately. If you know what the function does, just return the result directly. This is more concise and avoids unnecessary variables. However, sometimes if it's not clear what the function is doing, you can give the last variable a meaningful name and use it as self-documenting code.
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, }
Instead of using if else statement to set the value of the variable, you can use if expression to set it in one line like this. However, this reconstruction technique is somewhat questionable. Some people still prefer the first option, and that's fine.
if condition: x = 1 else: x = 2 # -> refactor x = 1 if condition else 2
When looking at this code, it is difficult to quickly grasp what is happening. There are multiple if-else statements and multiple indentations. Once you look closely, you may notice that the first if statement covers almost the entire function code, it's just that at the end we have the corresponding else clause, and we just return False.
We can move this else clause to the beginning. This is also called a cautionary statement. So if the condition is not true, we will not execute the rest of the function code. This removes an else clause, and now there is one less level of indentation in the entire code. This looks clearer and easier to understand.
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
This is an improved code from the previous example, but it still takes some time to understand what is going on here. So we want to check if we should wear a hat. The logic is this: if it’s raining, we always say True, if it’s not raining, and if the hat is stylish, we say True. One simple way we can greatly improve the readability of this logic is to move the allocation closer to its usage. Before using the if statement we need to understand the weather conditions. Now the fashion and style variables are only needed in the else clause, so move them down. It should be clearer now what's going on.
In Item 4 above, we can further shorten the code and return the evaluation style results immediately. In this case, is_stylish is a better name because it tells you that if the hat is stylish, you say True, otherwise you say False. So just keep the extra variables here.
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
This is another thing I see a lot. When you need to check if there is an element in a collection, for example in a list, you don't need to write if len(your_list) > 0. You can simply say if your_list. This is the pep 8 recommended approach, also known as truth testing. This is possible because in Python, empty sequences and sets evaluate to False. So this can be applied to strings, tuples, lists, dictionaries and sets.
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)
The above is the detailed content of Eight refactoring tips to make Python code more Pythonic. For more information, please follow other related articles on the PHP Chinese website!