📝 Programming

Functions: Best Practices

P
Author
Pyland
📅
Published
03.04.2026
⏱️
Reading time
2 min
👁️
Views
201
🌿
Level
Medium

Goal: Write functions that are easy to read, test, and reuse.


Rule 1: Name = Action

A function name is a verb plus an object. If you have to read the body to understand its purpose — the name is bad.

# Bad
def f(x, y): ...
def process(): ...

# Good
def calculate_total_price(base_price, quantity, tax_rate): ...
def validate_email(email): ...

Boolean functions start with is_, has_, can_:

def is_adult(age): return age >= 18
def has_permission(user): return user.role == "admin"
def can_withdraw(balance, amount): return balance >= amount

Rule 2: One Job (SRP)

# Bad: one function does everything
def process_user(name, age):
    if age < 18: return False
    with open("users.txt", "a") as f: f.write(f"{name},{age}\n")
    send_email(name)
    save_to_db(name, age)
    return True

# Good: each function does one thing
def is_adult(age): return age >= 18
def save_user_to_file(name, age): ...
def send_welcome_email(name): ...

def register_user(name, age):
    """Register a new user."""
    if not is_adult(age): return False
    save_user_to_file(name, age)
    send_welcome_email(name)
    return True

Rule 3: Return Results, Don’t Print

A pure function returns a value and doesn’t change external state.

# Bad: calculation and output mixed
def calculate_discount(price, pct):
    result = price * (1 - pct / 100)
    print(f"Total: {result}")
    return result

# Good: logic is separated from display
def calculate_discount(price, discount_percent):
    """Calculate the discounted price."""
    return price * (1 - discount_percent / 100)

def show_discount_info(price, discount_percent):
    final = calculate_discount(price, discount_percent)
    print(f"Price: {price} → {final}")

Rule 4: Descriptive Parameters

# Bad
def f(x, y, z): return x + y * z

# Good — named arguments at the call site
def calculate_total_price(base_price, quantity, tax_rate):
    """Calculate the total cost including tax."""
    return base_price + quantity * tax_rate

result = calculate_total_price(base_price=10, quantity=5, tax_rate=2)

More than 3–4 parameters — use a dict or dataclass.


Rule 5: Don’t Mutate Arguments

# Bad: modifies the passed list
def add_item(items, new_item):
    items.append(new_item)  # side effect!

# Good: returns a new list
def add_item(items, new_item):
    """Return a new list with the added item."""
    return items + [new_item]

Rule 6: Default Values

def create_account(name, balance=0, currency="USD"):
    """Create a bank account."""
    return {"name": name, "balance": balance, "currency": currency}

account1 = create_account("Alice")
account2 = create_account("Bob", 1000)
account3 = create_account("Charlie", 500, "EUR")

Rule 7: Document Functions

# Bad
def calc(p, d): return p - (p * d / 100)

# Good
def calculate_discounted_price(price, discount_percent):
    """
    Calculate the price after applying a discount.

    Args:
        price: The original item price
        discount_percent: Discount percentage (0-100)

    Returns:
        Price after the discount is applied

    Example:
        >>> calculate_discounted_price(1000, 20)
        800.0
    """
    return price * (1 - discount_percent / 100)

Rule 8: Keep Functions Short

A function should fit on one screen (20–30 lines). If it’s longer — split it.

def process_order(order_id):
    """Process the order end-to-end."""
    order = validate_order(order_id)
    if not check_inventory(order): return False
    save_order_to_database(order)
    send_confirmation_email(order)
    return True

Good Function Checklist

  • Name says WHAT it does (verb + object)
  • One job (SRP)
  • Returns a result, doesn’t print
  • Descriptive parameter names
  • Doesn’t mutate arguments
  • Has a docstring
  • Up to 20–30 lines
  • Maximum 3–4 parameters

Your reaction to the article

💬 Comments (0)

🔐 Sign in to leave a comment
🚪 Login
💭

No comments yet

Be the first to share your opinion about this article!

🔗 Similar

Similar articles

Continue learning with these materials

📝

map() — Transform Every Element!

Returns a map object — wrap it in list() to get a list.

📅 03.04.2026 👁️ 214
📝

filter() — Pick What You Need!

filter(None, data) removes all "falsy" values: None, False, 0, "", [], {}.

📅 03.04.2026 👁️ 218
📝

Lambda Functions

A lambda is a small, anonymous, single-line function.

📅 03.04.2026 👁️ 216

Did you like the article?

Subscribe to our updates and receive new articles first. Grow with PyLand!