Expense Tracker
A console-based expense tracker built entirely with Core Python, log expenses, review spending history, and see a running total, all backed by a simple, dependency-free accumulator pattern (total += new_expense). Built as Project 2 for the DecodeLabs Python Programming Internship, immediately after the to-do list manager, with input validation robust enough that no single bad entry can ever crash the session or corrupt the running total.
Why I Built This
This was built as Project 2 during the DecodeLabs Python Programming Internship, right after the to-do list manager; the brief was a simple expense tracker, but the real point was practicing state that has to accumulate correctly across an entire session rather than just get read and displayed back.
Keeping it to Core Python only, with no file storage or external libraries, meant the accumulator pattern had to do all the real work; there was no database or persistence layer to fall back on if the state handling itself was sloppy.
Technical Challenges
The real difficulty wasn't the arithmetic; it was making every single menu path defensive at the same time: rejecting non-numeric amounts, negative amounts, empty input, and out-of-range menu choices, and handling Ctrl+C / Ctrl+D gracefully instead of letting the program crash with a raw traceback.
Delete Last Expense needed the total and the expense list to stay perfectly in sync, subtracting the deleted amount back out rather than recomputing the total from scratch made the operation fast, but it also meant there was no safety net if the subtraction logic itself was ever wrong.
Data Organization
Every expense is stored as a single entry in an in-memory list, in the order it was added, no categories, dates, or tags, since the brief was about state and accumulation rather than a full budgeting feature set. View Expense History reads that list back in entry order, and View Total Expenses reports the accumulator alongside a simple count derived from the same list, so the two views can never disagree with each other about how many expenses exist.
Future Improvements
The most natural next step is categorization (tagging each expense so totals can be broken down by category instead of one flat number) followed by simple file persistence so a session's expenses don't disappear the moment the program exits. Both were deliberately left out here to keep the exercise focused on accumulation and state, not because they wouldn't be useful in a real version of this tool.
Key Decisions
The running total and expense list are the only state in the whole program, deliberately kept in memory rather than persisted, so the exercise stayed focused on getting accumulation and state management right instead of adding a storage layer.
Every input path (amount entry, menu selection) runs through the same category of validation: reject non-numeric, negative, empty, or zero-value input before it ever reaches the accumulator, so a single bad keystroke can never corrupt the running total.
Delete Last Expense explicitly subtracts the removed amount back out of the total rather than recalculating the total from the full list, which keeps the operation cheap but meant getting the subtraction logic exactly right so the total and the list could never drift out of sync.
What I Learned
The accumulator pattern (total = total + new_value) is a small idea that generalizes surprisingly far, it's the same mechanism behind ledgers, running statistics, and counters in much larger financial and analytics systems, and building it by hand here made that connection concrete.
Initializing state outside the loop, not inside it, turned out to be the detail that mattered most, state that resets on every pass through a while True loop isn't really state at all, and getting that boundary right was the actual lesson of the project.