Friday, 6 Mar 2026

Python Functions vs Subprocedures: Key Differences Explained

Understanding Python Subprograms: Functions vs Subprocedures

When structuring Python applications, breaking code into reusable subprograms significantly improves maintainability and reduces redundancy. While subprocedures and functions appear similar initially, understanding their distinct purposes is crucial for efficient programming. After analyzing this video tutorial, I believe many developers underestimate how return value handling fundamentally changes their application flow.

Core Concepts: Subprocedures and Functions Defined

Subprocedures (often called "subs") are reusable code blocks that perform actions without returning values. They handle tasks like calculations or operations internally. For example, a ticket pricing subprocedure might calculate costs and print results directly.

Functions, by contrast, specifically return values to the calling code using the return statement. As Python's official documentation notes, functions transform inputs into outputs that can be assigned to variables or used in expressions. This distinction becomes powerful in complex programs.

Practical Implementation Differences

Let's examine the video's ticket pricing example to see how calling mechanisms differ:

Subprocedure Implementation:

def calculate_ticket_price(adults, children):
    adult_price = 20 * adults
    child_price = 10 * children
    total = adult_price + child_price + 3  # £3 booking fee
    print(f"Total cost: £{total}")
    
# Calling the subprocedure
calculate_ticket_price(2, 3)  # Outputs: Total cost: £73

Function Implementation:

def get_ticket_price(adults, children):
    return (20 * adults) + (10 * children) + 3

# Calling the function
total_cost = get_ticket_price(2, 4)
print(f"Total cost: £{total_cost}")  # Outputs: Total cost: £83

Three key differences emerge:

  1. Return handling: Functions require capturing outputs (total_cost = ...)
  2. Flexibility: Function results can be used in expressions or nested calls
  3. Separation of concerns: Functions separate calculation from presentation

Advanced Usage: Nesting and Expression Chaining

Functions enable powerful techniques like nesting, where outputs become inputs for subsequent operations. Consider this real-world scenario:

# Nested function call
print("Total cost: £" + str(get_ticket_price(1, 2)))  # Outputs: Total cost: £43

Here's what happens step-by-step:

  1. get_ticket_price(1,2) returns 43 (integer)
  2. str() converts the integer to "43" (string)
  3. Concatenation creates "Total cost: £43"
  4. print() outputs the final string

Pro Tip: While nesting is efficient, temporary variables often improve readability for complex chains. Practice shows beginners should start with explicit assignments before mastering nesting.

When to Use Each Approach

Based on industry experience, here's my decision framework:

Use CaseSubprocedureFunction
Performing side effects✓ Ideal✗ Avoid
Reusable calculations✗ Limited✓ Best
Result chaining in expressionsImpossible✓ Essential
Code testabilityChallenging✓ Simplified

Critical Insight: Functions promote testability because return values can be validated without mocking output streams. This becomes crucial in professional development environments.

Actionable Implementation Checklist

  1. Identify return needs: Ask "Will this block produce a usable result?"
  2. Validate parameters: Add guard clauses like if adults < 0: return 0
  3. Avoid output in functions: Keep I/O separate from calculations
  4. Use type hints: Enhance readability with def get_ticket_price(adults: int, children: int) -> float:
  5. Test return cases: Verify edge cases (zero tickets, negative values)

Recommended Resources

  • Python Official Docs (Functions): Best for syntax reference (beginners)
  • "Fluent Python" by Luciano Ramalho: Deep dives into function design (intermediate)
  • pytest Framework: Simplifies function testing (all levels)

Conclusion

While Python blurs the line between functions and subprocedures syntactically, return value handling fundamentally changes their role in your code architecture. Functions provide the flexibility to build expression pipelines and return testable results, while subprocedures handle self-contained operations.

Which concept do you find more challenging to implement in your projects? Share your experience below - I'll address common pain points in follow-up content.