Python Beyond the Basics: Refactoring Object-Oriented Patterns into Functional Power
Overview
Functions in
Prerequisites
To follow this tutorial, you should have a solid grasp of basic Python syntax and the fundamentals of Object-Oriented Programming (OOP). Familiarity with

Key Libraries & Tools
- typing: Specifically the
CallableandListtypes to define function signatures. - functools: Specifically the
partialutility, which enables the creation of new functions from existing ones with pre-filled arguments.
Code Walkthrough
1. Defining the Function Type
Instead of a protocol class, we define a clear type alias using Callable. This ensures any strategy function we write takes a list of integers (prices) and returns a boolean.
from typing import Callable, List
TradingStrategy = Callable[[List[int]], bool]
2. The Closure Approach
Closures allow us to "bake" configuration into a function. By wrapping our strategy logic inside an outer function, the inner function retains access to the outer variables even after the outer function has finished execution.
def should_buy_average_closure(window_size: int) -> TradingStrategy:
def should_buy(prices: List[int]) -> bool:
# Accesses window_size from the outer scope
return sum(prices[-window_size:]) / window_size > prices[-1]
return should_buy
3. Partial Function Application
While closures work, they are verbose.
from functools import partial
def should_sell_minmax(prices: List[int], max_price: int) -> bool:
return prices[-1] > max_price
# Create a specific strategy with a pre-set max_price
sell_strategy = partial(should_sell_minmax, max_price=35000)
Syntax Notes
Python allows the use of underscores in numeric literals (e.g., 35_000) to improve readability. This has no impact on the value but makes it significantly easier to count zeros in high-frequency trading contexts. Additionally, when using Callable, the first argument is a list of input types, and the second is the return type.
Practical Examples
These techniques are ideal for trading bots where you need to swap out logic frequently. You can mix and match a "Buy" strategy from an average-based model with a "Sell" strategy from a min-max model without creating complex class hierarchies. This also applies to data processing pipelines where transformation steps need specific configurations.
Tips & Gotchas
Avoid confusing