🔍 Use Type Hints

Type hints are like labels that tell you what kind of data goes into a function and what comes out. Think of them as instruction tags that make your code self-documenting and help catch mistakes early.

Let's see the difference type hints make:

# WITHOUT type hints - unclear what the function expects
def calculate_tip(bill, rate):
    return bill * rate

# WITH type hints - crystal clear!
def calculate_tip(bill: float, rate: float) -> float:
    """Calculate tip amount for a restaurant bill."""
    return bill * rate

# WITHOUT type hints - what does this return?
def get_user_info(user_id):
    users = {'123': 'Alice', '456': 'Bob'}
    return users.get(user_id)

# WITH type hints - now we know it might return a name or None
def get_user_info(user_id: str) -> str | None:
    """Get username by ID, or None if not found."""
    users = {'123': 'Alice', '456': 'Bob'}
    return users.get(user_id)

# Examples showing the clarity
print("=== Type Hints Demo ===")

# Calculate tip - now we know we need numbers
bill_amount: float = 50.00
tip_rate: float = 0.18
tip: float = calculate_tip(bill_amount, tip_rate)
print(f"Bill: ${bill_amount}, Tip: ${tip:.2f}")

# Get user info - we know we need a string ID
user: str | None = get_user_info('123')
if user:
    print(f"Found user: {user}")
else:
    print("User not found")

🎯 The Basic Type Hint Syntax

Type hints use a simple pattern: variable: type and function(param: type) -> return_type:

Most Common Type Hints You'll Use

# The 4 most important type hints with simple examples

def create_welcome_message(name: str, age: int) -> str:
    """Create a welcome message - takes text and number, returns text."""
    return f"Welcome {name}! You are {age} years old."

def calculate_discount(price: float, discount_percent: int) -> float:
    """Calculate discounted price - takes decimal and whole number, returns decimal."""
    discount = price * (discount_percent / 100)
    return price - discount

def is_eligible_for_discount(age: int, is_student: bool) -> bool:
    """Check discount eligibility - takes number and True/False, returns True/False."""
    return age < 25 or is_student

def format_product_info(name: str, price: float, in_stock: bool) -> str:
    """Format product information - combines all 4 basic types."""
    status = "Available" if in_stock else "Out of Stock"
    return f"{name}: ${price:.2f} - {status}"

# Using the functions with clear type hints
print("=== Basic Type Hints in Action ===")

# Example 1: String and int input, string output
message: str = create_welcome_message("Bob", 22)
print(message)

# Example 2: Float and int input, float output
original_price: float = 100.00
discount_rate: int = 20  # 20%
final_price: float = calculate_discount(original_price, discount_rate)
print(f"Original: ${original_price}, Final: ${final_price}")

# Example 3: Int and bool input, bool output
user_age: int = 23
is_student_status: bool = True
gets_discount: bool = is_eligible_for_discount(user_age, is_student_status)
print(f"Gets discount: {gets_discount}")

# Example 4: Combining all types
product_name: str = "Python Course"
course_price: float = 49.99
available: bool = True
info: str = format_product_info(product_name, course_price, available)
print(info)

When You Need More Complex Types

Sometimes you need to handle lists, dictionaries, or situations where something might be missing. Here's when you need to import from the typing module:

Real-World Examples with Collections

# Collection type hints - when you work with lists and dictionaries

def get_average_grade(grades: list[float]) -> float:
    """Calculate average from a list of grade numbers."""
    if not grades:
        return 0.0
    return sum(grades) / len(grades)

def count_ages(people: dict[str, int]) -> str:
    """Count people by age groups from a name->age dictionary."""
    young = sum(1 for age in people.values() if age < 30)
    older = len(people) - young
    return f"Young (under 30): {young}, Older: {older}"

def find_student(students: list[str], name: str) -> str | None:
    """Find a student in the list, or return None if not found."""
    for student in students:
        if student.lower() == name.lower():
            return student
    return None  # This means "not found"

def create_user_profile(name: str, hobbies: list[str]) -> dict[str, str | list[str]]:
    """Create a user profile with name and hobbies."""
    return {
        'name': name,
        'status': 'active',
        'hobbies': hobbies
    }

# Examples showing how collections work
print("=== Collection Type Hints Demo ===")

# Working with list of numbers
student_grades: list[float] = [85.5, 92.0, 78.5, 95.0]
average: float = get_average_grade(student_grades)
print(f"Grades: {student_grades}")
print(f"Average: {average:.1f}")

# Working with dictionary
class_ages: dict[str, int] = {
    'Alice': 22,
    'Bob': 35,
    'Charlie': 19,
    'Diana': 28
}
age_summary: str = count_ages(class_ages)
print(f"Ages: {class_ages}")
print(f"Summary: {age_summary}")

# Working with optional returns (might be None)
student_list: list[str] = ['Alice Johnson', 'Bob Smith', 'Charlie Brown']
found_student: str | None = find_student(student_list, 'bob')

if found_student:
    print(f"Found: {found_student}")
else:
    print("Student not found")

# Creating complex return types
user_hobbies: list[str] = ['reading', 'coding', 'gaming']
profile: dict[str, str | list[str]] = create_user_profile('Alex', user_hobbies)
print(f"User profile: {profile}")

📋 Quick Type Hints Reference

What It Looks LikeWhat It MeansExample
name: strThis variable holds textname: str = "Alice"
age: intThis variable holds a whole numberage: int = 25
price: floatThis variable holds a decimalprice: float = 19.99
is_valid: boolThis variable holds True/Falseis_valid: bool = True
grades: list[float]This is a list of decimal numbers[85.5, 92.0, 78.5]
users: dict[str, int]Dictionary with text keys, number values{"alice": 25}
-> strThis function returns textReturns "Hello World"
-> NoneThis function returns nothingJust does something, no return
str | NoneEither text OR NoneCould be "hello" or None

🎯 Why Use Type Hints?

Simple Example: Type Hints Catching Errors

# This shows how type hints help catch common mistakes

def calculate_total_price(quantity: int, unit_price: float) -> float:
    """Calculate total price for items."""
    return quantity * unit_price

def greet_customer(name: str, order_total: float) -> str:
    """Create a greeting message with order total."""
    return f"Thank you {name}! Your total is ${order_total:.2f}"

# Correct usage - type hints help ensure we pass the right data
def process_order():
    """Process a customer order with proper types."""
    
    # These variables have clear types
    item_quantity: int = 3
    item_price: float = 25.99
    customer_name: str = "Alice"
    
    # Function calls are clear about what they expect
    total: float = calculate_total_price(item_quantity, item_price)
    message: str = greet_customer(customer_name, total)
    
    print(message)
    
    # These would be caught by type checkers BEFORE running:
    # calculate_total_price("3", 25.99)        # Error: quantity should be int, not str
    # calculate_total_price(3, "25.99")        # Error: price should be float, not str  
    # greet_customer(123, total)               # Error: name should be str, not int

# Demonstrate the benefits
def demonstrate_type_safety():
    """Show how type hints improve code safety."""
    
    print("=== Type Hints Benefits Demo ===")
    
    # Clear, type-safe code
    items: int = 5
    price_per_item: float = 12.50
    total_cost: float = calculate_total_price(items, price_per_item)
    
    print(f"Items: {items}")
    print(f"Price per item: ${price_per_item}")
    print(f"Total cost: ${total_cost}")
    
    # Your IDE would warn you about these mistakes:
    # Wrong types would be caught before running
    customer: str = "Bob"
    greeting: str = greet_customer(customer, total_cost)
    print(greeting)

process_order()
demonstrate_type_safety()

🎯 Key Takeaways

🚀 What's Next?

Congratulations! You've completed the Python Best Practices section. You now have the knowledge to write professional, maintainable Python code.

Consider exploring: Advanced Python topics like decorators, context managers, metaclasses, or web frameworks like Django and Flask.

Keep practicing and applying these best practices in your projects! 🐍✨

Was this helpful?

😔Poor
🙁Fair
😊Good
😄Great
🤩Excellent