python refactoring Python code

  • Converting a for loop into a list/dictionary/set expression
    A situation we often encounter is to create a set of values.
    For example, if we create a list and then iteratively fill it with values, here we want to create a list of cubic numbers. The standard method for most languages ​​is as follows:
cubes = []
for i in range(20):
    cubes.append(i ** 3)

In Python, we can use list expressions to generate the required data. You can simplify the code to one line, save the definition list, and then go to the slightly tedious operation of filling the list.

cubes = [i ** 3 for i in range(20)]

Look, we have converted three lines of code into one line, which is undoubtedly a good choice-your eyes don't need to check the code up and down.

Compressing the code to one line makes reading more difficult, but this is not the case for deduced expressions. All the elements you need are well presented, and once you get used to the syntax, it is actually more readable than the for loop version.

Another point is that assignment is now more like an atomic operation-we declare what cubes are, instead of giving instructions on how to construct it. This makes the code more comfortable to read because we care about what the variable cubes are, not the details of its construction.

Finally, expressions are usually faster than building collections in loops, which is also an important factor if performance is considered.

  • Replacing assignment with incremental assignment
    Incremental assignment is a fast and simple Python syntax.
    As long as there is code like this:
count = count + other_value

Can be replaced with the following code:

count += other_value

The code is short and clear-we don't need to think about counting variables twice. Other operators that can be used include -=, *=, /= and **=.
But one thing needs to be a little more careful, the type you want to assign to must define the appropriate operator. For example, numpy arrays do not support the /= operation.

  • Inline variables that are used only once
    One of the situations we often see in people's code is to assign the result to a temporary variable and then return it immediately.
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

In fact, a better way is to return the result directly instead of using a temporary variable to store the result

def state_attributes(self):
    """Return the state attributes."""
    return {
    
    
        ATTR_CODE_FORMAT: self.code_format,
        ATTR_CHANGED_BY: self.changed_by,
    }

This can shorten the code and delete unnecessary variables, thereby reducing the mental effort to read the code.
Temporary variables may be useful if they are used as parameters or conditions, and the name can represent content. In the above example, the state attribute is returned, and state_attr does not provide any additional information. Therefore, it is not necessary to assign the result to a temporary variable.

  • Replace if statements with if expressions
    A situation often encountered is that you often want to set a variable to one of two different values.
if condition:
    x = 1
else:
    x = 2

This can be written on one line using Python's conditional expression syntax (python's ternary operator version):

x = 1 if condition else 2

This is definitely more concise, but it is a more controversial refactoring (like list expressions). Some programmers don't like such expressions because they feel that they are more difficult to parse than writing the if condition completely.
Our point is that as long as the conditional expression is short and suitable for merging, it is an improvement and efficiency. Similar to the list expression example, when we read the code, we usually don't need to know how x is assigned, we just need to see that it is assigned, and then move on.

  • Replace unwanted expressions with generators

One trick is that functions like any, all, and sum allow generators instead of collections. This means, instead of doing this:

hat_found = any([is_hat(item) for item in wardrobe])

You can change the code to:

hat_found = any(is_hat(item) for item in wardrobe)

This will remove a pair of parentheses and make the code slightly clearer. If the any function finds a result, it will return immediately without having to build the entire list. This can lead to performance improvements.

Please note that we are actually passing the generator to any(). Strictly speaking, the code should look like this:

hat_found = any((is_hat(item) for item in wardrobe))

But Python allows you to omit these parentheses. The following are the standard library functions that accept generators:

'all', 'any', 'enumerate', 'frozenset', 'list', 'max', 'min', 'set', 'sum', 'tuple'
  • Reduce the condition to a return statement

The last reconstruction technique introduced is that the function needs to return a True or False result. A common method is:

def function():
    if isinstance(a, b) or issubclass(b, a):
        return True
    return False

However, it is more concise to return the result directly, as shown below:

def function():
    return isinstance(a, b) or issubclass(b, a)

This can be done only when the calculation result of the expression is a Boolean value. E.g

def any_hats():
    hats = [item for item in wardrobe if is_hat(item)]
    if hats or self.wearing_hat():
        return True
    return False

In this example, hat and self.wearing_hat() can be combined into a bool list by bool(), which can eliminate the if condition and simplify the program.

def any_hats():
    hats = [item for item in wardrobe if is_hat(item)]
    return bool(hats or self.wearing_hat())

Reference link

Guess you like

Origin blog.csdn.net/weixin_42464956/article/details/110791616