What It Is
The Strategy pattern makes an algorithm swappable: the surrounding code stays the same, and the interchangeable part — how to price, how to sort, how to compress — is plugged in as a value.
This is the pattern Python simplifies the most: since functions are first-class values, a strategy is often just a plain function. No protocol, no class — assign a different function and the behavior changes.
Example: Swappable Pricing
checkout() never changes; the pricing rule is a function in a field. Regular price, Black Friday, member discount — three functions, one shop.
The strategy is a function
Three checkouts of the same 50 give three totals — only the assigned function differs. This is also how sorted() works: the key function you hand it is the comparison strategy.
Output: complete Python program
from typing import Callable
# The strategy is just a function in Python.
Pricing = Callable[[float], float]
def regular(price: float) -> float:
return price
def black_friday(price: float) -> float:
return price * 0.7
def member(price: float) -> float:
return price - 5
class Shop:
def __init__(self, pricing: Pricing) -> None:
self.pricing = pricing
def checkout(self, price: float) -> None:
print(f"total: {self.pricing(price):.2f}")
shop = Shop(regular)
shop.checkout(50)
shop.pricing = black_friday
shop.checkout(50)
shop.pricing = member
shop.checkout(50)
When to Use It
Use it whenever an algorithm varies while its surroundings do not: pricing rules, retry policies, sorting orders, validation modes.
Skip it when there is one algorithm and no realistic second. Use a class instead of a function only when a strategy needs its own state or several methods.
Pros and Cons
Pros: behavior swaps at run time; each strategy is small and testable alone; in Python it is nearly free — a plain function and an assignment.
Cons: the chosen strategy is invisible at the call site — debugging means finding what was assigned; too many micro-strategies fragment simple logic.