Thursday, 27 June 2024

Refactoring Python Code: A Lazy Coder's Guide

Refactoring code is often viewed as a tedious task, especially for those of us who would rather be creating something new than polishing the old. However, even the laziest of coders can appreciate the benefits of cleaner, more efficient, and more maintainable code. In this blog post, we’ll go through some basic Python code refactoring techniques, transforming cluttered scripts into streamlined modules that even the laziest coder wouldn’t mind tweaking.

Why Refactor?

Before we dive into the examples, let’s establish why refactoring is crucial:

  • Improved readability: Cleaner code is easier to read and understand.
  • Easier maintenance: It’s simpler to update and debug well-organized code.
  • Enhanced performance: Removing redundancies and optimizing processes can boost performance.
  • Scalability: Well-factored code is easier to scale with your project’s needs.

Example 1: Simplifying Conditional Statements

Original Code

Here’s a typical snippet that could use some cleaning up:

def check_discount(day):
    if day == "Monday":
        return 10
    elif day == "Tuesday":
        return 15
    elif day == "Wednesday":
        return 20
    elif day == "Thursday":
        return 20
    elif day == "Friday":
        return 25
    else:
        return 0

Refactored Code

We can use a dictionary to map days to discounts, simplifying the function significantly:

def check_discount(day):
    discount_mapping = {
        "Monday": 10,
        "Tuesday": 15,
        "Wednesday": 20,
        "Thursday": 20,
        "Friday": 25
    }
    return discount_mapping.get(day, 0)

Example 2: Combining Similar Functions

Original Code

Let’s say we have multiple functions that do almost the same thing:

def print_message_one():
    print("Hello from Function One!")

def print_message_two():
    print("Hello from Function Two!")

Refactored Code

We can combine these functions into one, using a parameter to customize the message:

def print_message(msg):
    print(f"Hello from {msg}!")

Example 3: Removing Redundant Code

Original Code

Sometimes, we find ourselves writing more code than necessary:

def is_even(num):
    if num % 2 == 0:
        return True
    else:
        return False

Refactored Code

This can be condensed into a single line:

def is_even(num):
    return num % 2 == 0

Example 4: Using List Comprehensions

Original Code

Here’s how you might currently be handling lists:

numbers = [1, 2, 3, 4, 5]
squared_numbers = []
for number in numbers:
    squared_numbers.append(number ** 2)

Refactored Code

A list comprehension makes this much more concise:

numbers = [1, 2, 3, 4, 5]
squared_numbers = [number ** 2 for number in numbers]

Refactoring doesn’t have to be a chore. By making it a regular part of your coding routine, you ensure that your codebase remains easy to manage, extend, and debug. Lazy coders, rejoice! The less clutter there is, the less there is to manage, and the easier your future coding sessions will be. Happy coding, and keep it clean!

Example 5: Consolidating Loops

Original Code

Multiple loops iterating over the same list to perform different tasks can be combined:

names = ["Alice", "Bob", "Charlie", "David"]
lowercase_names = []
lengths = []

for name in names:
    lowercase_names.append(name.lower())

for name in names:
    lengths.append(len(name))

Refactored Code

Combine the operations in a single loop:

names = ["Alice", "Bob", "Charlie", "David"]
lowercase_names = []
lengths = []

for name in names:
    lowercase_names.append(name.lower())
    lengths.append(len(name))

Example 6: Using Generator Expressions

Original Code

Building a list to pass to a function:

numbers = range(1, 101)
even_numbers = [num for num in numbers if num % 2 == 0]
sum_even_numbers = sum(even_numbers)

Refactored Code

Use a generator expression to avoid creating an intermediate list:

numbers = range(1, 101)
sum_even_numbers = sum(num for num in numbers if num % 2 == 0)

Example 7: Reducing Nesting

Original Code

Deeply nested conditional statements:

def process_order(order):
    if order.is_paid:
        if order.amount > 1000:
            if order.in_stock:
                ship_order(order)
            else:
                notify_out_of_stock(order)
        else:
            notify_amount_too_low(order)
    else:
        notify_payment_required(order)

Refactored Code

Reduce nesting by using early returns:

def process_order(order):
    if not order.is_paid:
        notify_payment_required(order)
        return
    if order.amount <= 1000:
        notify_amount_too_low(order)
        return
    if not order.in_stock:
        notify_out_of_stock(order)
        return
    ship_order(order)

Example 8: Utilizing Set Operations

Original Code

Checking for duplicates using loops:

items = ["apple", "banana", "apple", "orange", "banana", "banana"]
duplicates = []

for item in items:
    if items.count(item) > 1 and item not in duplicates:
        duplicates.append(item)

Refactored Code

Use set operations to find duplicates more efficiently:

items = ["apple", "banana", "apple", "orange", "banana", "banana"]
duplicates = set([item for item in items if items.count(item) > 1])

Example 9: Using Built-in Functions

Original Code

Manually reversing a string:

s = "hello"
reversed_s = ''
for char in s:
    reversed_s = char + reversed_s

Refactored Code

Use Python’s built-in function:

s = "hello"
reversed_s = s[::-1]

Example 10: Applying the Walrus Operator

Original Code

Code that evaluates an expression multiple times:

data = "some long string"
if len(data) > 10:
    print(f"String is too long ({len(data)} characters)")

Refactored Code

Use the walrus operator to avoid evaluating the expression multiple times:

data = "some long string"
if (n := len(data)) > 10:
    print(f"String is too long ({n} characters)")

Labels:

0 Comments:

Post a Comment

Note: only a member of this blog may post a comment.

<< Home