🔍 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 Like | What It Means | Example |
---|---|---|
name: str | This variable holds text | name: str = "Alice" |
age: int | This variable holds a whole number | age: int = 25 |
price: float | This variable holds a decimal | price: float = 19.99 |
is_valid: bool | This variable holds True/False | is_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} |
-> str | This function returns text | Returns "Hello World" |
-> None | This function returns nothing | Just does something, no return |
str | None | Either text OR None | Could 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?
Track Your Learning Progress
Sign in to bookmark tutorials and keep track of your learning journey.
Your progress is saved automatically as you read.