Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
301: Type Checking with mypy
Imagine you're preparing for a long-haul flight. You have a pre-flight checklist: fuel levels checked, flaps tested, engines humming. You don't wait until you're 30,000 feet in the air to realize you forgot to lock the cargo bay; you want that mistake caught while the plane is still sitting safely on the tarmac. If you find the error during the checklist, it's a five-minute fix. If you find it mid-flight, it's a catastrophe.
In Python, running your code is "taking off." Type hints are your checklist. But here is the catch: Python itself doesn't actually care about those hints. It ignores them completely at runtime. This is where mypy comes in. Mypy is your ground crew. It reads your checklist and your code, then tells you exactly where you're about to crash before you ever hit the "Run" button.
Catching the "Invisible" Crash
I've spent far too many late nights debugging TypeError: unsupported operand type(s) for -: 'float' and 'str'. Usually, it happens because some function three levels deep in the call stack decided to return a string instead of a number, and I didn't notice until the app crashed in production.
Look at this snippet. It looks fine, and it works if you pass it the right data:
def apply_discount(price: float, discount: float) -> float:
return price - discount
# This works great
print(apply_discount(100.0, 15.0))
# This will crash at runtime, but Python won't warn you while writing it
print(apply_discount(100.0, "15.0"))
If you run this with the standard Python interpreter, it just crashes. But if you run mypy over this file, it screams at you immediately: Argument 2 to "apply_discount" has incompatible type "str"; expected "float". It found the bug without ever executing a single line of code.
Bridging the Gap Between Hints and Reality
The magic of mypy is that it turns Python's dynamic nature into something more predictable. You aren't changing how the code runs—you're just adding a layer of verification. To get this working, you'll need to install it via pip (pip install mypy) and then run it from your terminal like this:
mypy my_script.py
I highly recommend doing this as part of your CI/CD pipeline or as a pre-commit hook. I don't trust my own brain to remember every type across a 1,000-line file, and I certainly don't trust my teammates to always pass the correct types into my functions. Mypy becomes the "single source of truth" that keeps the codebase honest.
Handling the "Maybe" Types
One thing that usually trips people up is when a value might be a certain type, or it might be None. In the old days, we just hoped for the best. Now, we use Optional from the typing module.
If you tell mypy a variable is a float, but then you try to assign None to it, mypy will flag it. This forces you to actually handle the None case with an if statement, which prevents the dreaded AttributeError: 'NoneType' object has no attribute...
from typing import Optional
def get_user_score(user_id: int) -> Optional[int]:
# Imagine this looks up a score in a database
if user_id == 1:
return 100
return None
score = get_user_score(2)
# mypy will warn you here: "Item 'None' of 'Optional[int]' has no attribute 'bit_length'"
# print(score.bit_length())
if score is not None:
print(score.bit_length()) # Now mypy is happy
📋 Practical Task
Fixing the Inventory Management System
You've been handed a script for a warehouse inventory system. The previous developer added some type hints, but they were sloppy, and the code is riddled with potential runtime crashes. Your goal is to use mypy to identify the type mismatches and fix the code so that it passes a static type check.
The Buggy Code:
from typing import List, Optional
def calculate_total_value(items: List[float], tax_rate: float) -> float:
total = sum(items)
return total * (1 + tax_rate)
def get_item_price(item_id: int) -> Optional[float]:
prices = {1: 10.50, 2: 20.00, 3: 5.25}
return prices.get(item_id)
# --- THE PROBLEM AREA ---
inventory_ids = [1, 2, 4] # Item 4 doesn't exist in the prices dict
prices = []
for i in inventory_ids:
price = get_item_price(i)
prices.append(price) # Mypy should flag this: you're adding Optional[float] to List[float]
# This will crash if any item was None
final_value = calculate_total_value(prices, 0.07)
print(f"Total Value: {final_value}")
Your Task:
- Install
mypyand run it against this script. - Identify the two primary type errors mypy reports.
- Modify the loop and the
priceslist definition so that only actual floats are passed tocalculate_total_value. - Ensure the final script runs without any mypy errors.
There are no comments for now.