Code Review · Python
Python Code Review: Missing Type Hints
Review Python code where missing type hints make the function contract unclear.
Code Review Exercise
Review the following Python function. The code works for the happy path, but it is harder to understand and easier to misuse than it needs to be.
def apply_discount(order, discount):
total = 0
for item in order["items"]:
total += item["price"] * item["quantity"]
if discount:
total = total - discount
return round(total, 2)What issues would you mention in a code review?
Review Findings
Issue #1: The input shape is unclear
The function expects order to be a dictionary with an items key. Each item is also expected to containprice and quantity. None of that is obvious from the function signature.
Issue #2: The discount type is ambiguous
Is discount a number, percentage, coupon object, string code, or nullable value? Without type hints, callers have to inspect the implementation or guess.
Issue #3: Truthiness can hide valid values
The check if discount: treats 0,None, and other falsy values the same way. If those values have different meanings, this can become a correctness bug.
Issue #4: Missing return type
The function returns a rounded number, but the signature does not say whether callers should expect an int,float, Decimal, or something else.
Why Type Hints Help In Review
Type hints are not only for type checkers. In interviews and real code reviews, they make the contract of a function easier to see.
A reviewer can quickly answer:
- What input shape does this function expect?
- Can a value be
None? - What does the function return?
- Is a dictionary the right model, or should this be a class/dataclass?
Better Version With Type Hints
from typing import TypedDict
class OrderItem(TypedDict):
price: float
quantity: int
class Order(TypedDict):
items: list[OrderItem]
def apply_discount(order: Order, discount: float | None = None) -> float:
total = 0.0
for item in order["items"]:
total += item["price"] * item["quantity"]
if discount is not None:
total -= discount
return round(total, 2)This version makes the expected structure visible. It also separatesNone from numeric values like 0.
Even Better Design Option
If this logic grows, a dictionary may not be the best model. A dataclass can make the domain clearer.
from dataclasses import dataclass
@dataclass(frozen=True)
class OrderItem:
price: float
quantity: int
@dataclass(frozen=True)
class Order:
items: list[OrderItem]
def apply_discount(order: Order, discount: float | None = None) -> float:
total = sum(item.price * item.quantity for item in order.items)
if discount is not None:
total -= discount
return round(total, 2)This may be overkill for a tiny script, but it is often cleaner in application code where the data shape matters.
What Not To Do
Do not turn every small script into a type-heavy design exercise. The goal is not to add ceremony everywhere.
A good review comment is balanced:
The function depends on a specific dictionary shape, but the signature does not show that. Consider adding type hints or a small dataclass if this is production code.
Interview Follow-Ups
Do Python type hints affect runtime behavior?
Usually no. Type hints are mainly for readability, IDE support, static analysis, and tools like mypy or pyright. Python does not enforce them by default at runtime.
When are type hints most useful?
They are especially useful at module boundaries, public functions, service methods, data models, and places where the input shape is not obvious.
Should every local variable have a type hint?
No. Over-annotating simple local variables can add noise. Function parameters, return types, and complex data structures are usually more valuable.
What is the difference between TypedDict and dataclass?
TypedDict describes the expected shape of a dictionary. A dataclass creates an actual class with named fields. TypedDict is useful when dictionaries are already part of the interface; dataclasses are often cleaner for domain objects.
What Interviewers Expect
A strong code review answer should not simply say, “add type hints.” Explain why they matter here.
- The input structure is hidden.
- The discount contract is unclear.
- The return type is not obvious.
- The code may benefit from
TypedDictor a dataclass. - Do not add unnecessary ceremony for tiny throwaway scripts.