- Lab
-
Libraries: If you want this lab, consider one of these libraries.
- Core Tech
Savings Goal Simulator in Python
Build a standalone Python command-line savings goal simulator that projects balance growth over time. You will implement numeric conversions, month-by-month calculations, list-based record keeping, loop control with early exit, and formatted console reporting.
Lab Info
Table of Contents
-
Challenge
Step 1: Explore the savings goal simulator project
Welcome to the lab. In this project, you will turn a partially scaffolded Python command-line program into a working savings goal simulator that can project balance growth over time. The lab starts with a clean package structure, a small CLI entry point, and a focused test suite, but the key learning logic has been left incomplete so you can implement it yourself.
At a conceptual level, this application combines a few foundational programming ideas that appear in many real systems. First, user input almost always arrives as text, so converting strings into the right numeric types is essential before any meaningful computation can happen. Second, financial and planning tools often perform the same calculation over and over across a sequence of periods, which makes loops a natural fit. Third, once repeated results are produced, they need to be stored in a data structure so other parts of the program can summarize or display them later. In this lab, that structure is a list of monthly records.
The project is deliberately organized into three main areas:
-
app/travel_fund.py- Contains the core business logic:
- Rate conversion
- Monthly calculations
- Projection loops
- Record summarization
- Contains the core business logic:
-
app/main.py- Contains the command-line workflow:
- Reading input
- Printing per-month output
- Printing the final summary
- Contains the command-line workflow:
-
The
solutions/directory contains step-based reference implementations that you can use to verify your work and troubleshoot issues.
Key terminology:
input(): A built-in Python function that reads text entered by the user.range(): A built-in function commonly used withforloops to repeat an action a fixed number of times.- Record list: In this lab, a four-item list representing one month as
[month, deposit, interest, ending_balance]. - Pure function: A function that returns a value based only on its inputs and does not perform unrelated side effects.
What you'll accomplish:
- Implement reusable helpers for numeric conversion and one-month savings growth.
- Build list-based monthly projections with
forloops and conditional early exit. - Connect the CLI flow from user prompts to printed reports.
- Aggregate stored records into a final progress summary. info> This lab experience was developed by the Pluralsight team using an internally developed AI tool. All sections were verified by human experts for accuracy prior to publications. However, content may still contain errors or inaccuracies, and we recommend independent verification.
To report a problem or provide feedback, click here. Feedback may be used to improve accuracy in accordance with our Privacy Policy.
-
-
Challenge
Step 2: Build the core monthly calculation helpers
This step establishes the mathematical and formatting building blocks that the rest of the simulator depends on. Before a projection loop can run for many months, the program needs small, trustworthy helpers that each do one clear job well. That structure mirrors real production code, where complicated workflows are easier to understand and test when the low-level logic is split into small units.
The first concept in this step is representation. An annual rate is usually entered as a percentage, but calculations are easier when the value is stored as a decimal. A user thinks in terms like
6%, while code often needs something like0.005for a monthly rate. Converting between those representations is simple arithmetic, but doing it in one dedicated function prevents the same formula from being copied around the project.The second concept is composition: a one-month growth function can focus only on interest and balance updates, while a separate formatting function can focus only on presentation. That separation keeps business logic and display concerns from becoming tangled together.
Architecturally, all of the code in this step lives in
app/travel_fund.py, the module that holds the simulator's reusable logic. Later steps will import these helpers into the CLI and loop functions rather than rewriting the calculations in multiple places.Key terminology:
- Percentage: A value out of one hundred, such as
6for six percent. - Decimal rate: A calculation-ready form such as
0.06per year or0.005per month. - f-string: A Python string literal that can embed expressions and formatting instructions.
- Helper function: A small function created to handle one narrow, reusable task.
What you'll accomplish:
- Convert annual percentage rates into monthly decimal rates.
- Compute one month of savings growth from a starting balance.
- Build a formatted report string for one saved month. ### Context The simulator accepts a yearly return rate from the user, but the program applies growth one month at a time. That means every later calculation depends on a correct conversion from annual percent form to monthly decimal form. Getting this helper right early removes confusion from the loop logic you will build later, because every month can reuse the same already-converted rate.
A well-named conversion function also improves maintainability. If the formula ever needs to change, perhaps because the program later supports different compounding rules, there is exactly one place to update. In real applications, small numeric helpers like this reduce copy-and-paste mistakes and make tests much more targeted.
Concepts
A percentage such as
6is not the same thing as the decimal0.06; the decimal is what most formulas actually need. In Python, division with/returns a numeric result, and chaining two divisions is a straightforward way to move from annual percentage to monthly decimal. Separating this logic into a pure function is important because pure functions are easy to test: given the same input, they always return the same output and do not depend on prompts, files, or printed text. That predictability is one reason small, single-purpose functions are common in reusable Python code. Now that the rate conversion is isolated, the next logical piece is the actual month-level balance update. This lets you combine the converted rate with a current balance and a planned deposit. Once that helper works, a laterforloop can simply repeat it for each month without needing to know the math details. ### Context Before the simulator can forecast several months, it needs a function that answers a simpler question: given a starting balance, monthly rate, and planned deposit, what happens by the end of the month? That one-month calculation becomes the foundation for the projection loops you will build later.This design mirrors how many business systems are built. Developers often model one transaction, one billing cycle, or one inventory update first, and then apply that logic repeatedly through loops or workflows.
Concepts
This task uses a common programming pattern: calculate an intermediate value, then use it to derive a final result. Here, the intermediate value is the monthly interest earned, and the final result is the ending balance after both interest and deposit are applied.
Returning multiple values as a tuple is an idiomatic Python technique for small, closely related results. By returning both interest and ending balance together, the program can reuse the numbers for later reporting. With the core arithmetic in place, the next improvement is readability. Raw numbers are useful for calculations, but users benefit from concise, well-formatted text. The final helper in this step will convert one month's numeric result into a line the CLI can print later. ### Context
Users usually do not want to interpret a list like
[3, 250, 12.5, 1512.5]directly. A report helper translates that internal record into readable text, making the command-line output easier to understand.This function will later support the
print_projection()routine in the CLI module by creating a consistent report line for each month.Concepts
Python f-strings can combine values and formatting in a single string. Formatting a value with
:.2fdisplays exactly two digits after the decimal point, which is useful for currency-style output.This task also introduces a common pattern: returning a formatted string from a helper function so it can be reused wherever output is needed.
In this step, you built three foundational helpers:- A rate converter
- A one-month growth calculator
- A formatter for monthly reports
Together, these helpers provide the foundation for the next step, where you will use loops to project growth over multiple months, store results in a list, and stop early when a savings goal is reached.
- Percentage: A value out of one hundred, such as
-
Challenge
Step 3: Project many months with loops and control flow
This step moves from single calculations to repeated simulation. Once a program can compute one month correctly, a
forloop can apply that same logic across many months and collect the results. This is where the application starts to feel like a real planning tool rather than a handful of disconnected helpers.The central concept here is iterative state. A loop often carries forward one or more values from one iteration to the next, and in this project the running savings balance is that evolving state. Each month depends on the ending balance from the previous month, so the code must update the value in the right order every time through the loop. The second major concept is accumulation. Rather than printing and forgetting each month immediately, the program stores each result in a list. That record list gives later functions something to summarize, inspect, and display. A third concept is control flow. Not every loop needs to run to its maximum length; sometimes a business rule says the process can stop early. In Python,
ifstatements andbreakmake that behavior explicit.From an architecture standpoint, these features still belong in
app/travel_fund.py. The projection functions are part of the application's calculation engine, while the CLI file will simply call them later. Keeping loop logic in the core module makes it easier to test the math without relying on interactive input.Key terminology:
- Iteration: One pass through a loop.
- Accumulator: A variable or list that collects results across repeated steps.
- Boundary condition: A special case at the edge of expected values, such as exactly meeting a target.
break: A Python statement that exits the nearest loop immediately.
What you'll accomplish:
- Build a month-by-month projection stored in a list.
- Add a Boolean helper for target detection.
- Stop the loop early and trim the final deposit to match the target exactly. ### Context
A realistic savings planner needs to project growth across many months, not just one. Instead of performing the same calculation manually, the program can repeat the one-month growth helper inside a loop and store the results for each month.
Concepts
A
forloop is useful when the number of repetitions is known in advance. Python'srange()function commonly provides the sequence of loop counters, which can be adjusted when month numbering should begin at1instead of0.This task also introduces a running balance. After each month is calculated, the ending balance becomes the starting balance for the next month. Each month's result is then added to a list so the full projection can be returned at the end. The fixed-length loop gives you a complete projection history, but the application still needs a readable way to express the idea of success against a target. The next helper is intentionally tiny, yet it makes later conditionals more expressive and easier to test. ### Context
The projection logic needs a simple way to determine whether a savings goal has been reached. Rather than repeating the same comparison throughout the program, this task creates a small helper that answers that question directly.
Concepts
A Boolean function returns either
TrueorFalse, making it a natural fit for conditions. Boundary handling is important here because reaching the target exactly should count as success. In Python,>=means greater than or equal to, which matches that requirement. With a loop and a goal check available, the simulator is ready for its most realistic behavior so far: ending early when the target is achieved. This adds an important control-flow technique and introduces the idea that the final month may need slightly different handling from the earlier ones. ### Context Many real-world simulations and planning tools do not simply run for a fixed number of periods. They also watch for a business condition that can end the process early, such as a budget being exhausted, an inventory threshold being reached, or a goal being met. In this lab, the meaningful stopping condition is reaching the target savings amount.There is one extra nuance that makes this task more realistic: the final contribution should not overshoot the goal when a smaller deposit would finish the job. That kind of end-condition adjustment appears often in finance, scheduling, and resource planning programs. It keeps the output aligned with the user's actual objective instead of continuing mechanically.
Concepts
This task combines looping, conditional logic, and an early-exit statement. A
breakexits the current loop immediately, which is useful when the program has already achieved the desired result. Before breaking, the code must still save the final month's record so the history stays complete. The task also illustrates a pattern of calculating an actual amount from a planned amount: the planned deposit is the normal case, but the actual final deposit may be reduced based on the remaining gap to the target. This difference between planned and actual values is common in production systems. At this point, the simulator can generate a full list of monthly records and stop early when the target is reached. That gives the project its core computational behavior. In the next step, you will connect these reusable functions to the command-line interface so a user can supply inputs and see the projection printed to the console. -
Challenge
Step 4: Connect the command-line workflow
This step connects the core logic to an actual user interaction flow. The calculation module already knows how to project savings growth, but a user-facing program also needs prompts, input conversion, and a coordinating function that calls the right pieces in the right order. In many applications, this layer is sometimes called the presentation or entry-point layer.
One major concept here is type conversion at system boundaries. Interactive input arrives as text, even when the user intends to enter a number. That means a CLI must immediately translate strings into the numeric types expected by the calculation layer. Another concept is orchestration. The
mainfunction in a small Python program typically does not perform every detail itself; instead, it coordinates several helper functions. This is similar to how controllers, route handlers, or service entry points work in larger systems: they gather input, call domain logic, and trigger output.In this project,
app/main.pyserves exactly that role. It imports reusable logic fromapp/travel_fund.py, gathers user input, runs the projection, prints per-month lines, and prepares summary data. Keeping that coordination separate from the business calculations makes the project easier to read and easier to test.Key terminology:
- CLI: Command-line interface, a text-based way for users to interact with a program.
- Orchestration: Coordinating several smaller operations into one complete workflow.
- Unpacking: Assigning elements from a tuple to multiple variables in one statement.
- Side effect: An observable action such as prompting the user or printing output.
What you'll accomplish:
- Prompt for user inputs and convert them into numeric values.
- Connect input, projection, printing, and summary calculation in
main. - Produce a runnable end-to-end CLI workflow. ### Context The core module is designed to be reusable, but right now the program still needs a proper entry point that gathers planning values from a human. A command-line tool becomes much more useful when someone can run it, answer a few prompts, and immediately see the result. That makes input handling the first bridge between the user and the simulator's calculation engine.
Accurate input conversion is also critical because every later calculation depends on these values. A string that looks like a number is still just text to Python until you convert it. If this boundary is handled correctly, the rest of the application can assume it is working with proper numeric data.
Concepts
The built-in
input()function always returns a string. To turn that string into something the projection functions can use, Python provides constructors such asfloat()andint()that parse text into numeric types. Choosing the right type matters: dollar amounts and rates may include decimals, while the number of months should be a whole number for looping withrange(). Returning the converted values as a tuple is a compact way to hand multiple related inputs to the coordinator function while keeping the input routine focused on one responsibility. With clean numeric input available, the final piece of the CLI layer is orchestration. The next task turns the individual helpers into a complete flow, where one function prompts the user, runs the projection, prints the monthly results, and prepares summary data for the closing message. ### ContextIn a well-structured application, the top-level workflow should read like a short narrative of the program's behavior. That is what
main()will provide in this step. The function coordinates the helpers you built earlier and keeps the overall workflow easy to follow.This kind of coordinator pattern appears throughout software. A web route handler may parse a request, call business logic, format a response, and return it. A desktop button handler may gather form data, call a service, and update the screen. Here,
main()serves the same role for a command-line application.Concepts
Orchestration functions often rely on tuple unpacking and predictable helper behavior. Because each helper returns the values needed by the next step,
main()can coordinate the workflow by calling them in sequence.Returning the records, goal flag, and summary from
main()also makes the workflow easier to verify and test. You now have a runnable command-line workflow that collects inputs and produces month-by-month output. The remaining work focuses on end-of-run reporting: turning the stored record list into totals and printing a polished closing message for the user. -
Challenge
Step 5: Add summary reporting and finish the planner
The final step turns raw monthly history into a concise end-of-run report. The simulator already creates a list of records and prints each month, but users also benefit from aggregate information such as total deposits, total interest earned, and whether the goal was achieved. Summaries are an important part of many applications because they transform detailed event data into a quick decision-making view.
The main programming idea in this step is aggregation. An aggregation function loops over existing records and accumulates totals, counts, or final values. This is common in finance, reporting dashboards, analytics pipelines, and many kinds of business software. Because the project stores one month at a time in a consistent record structure, summary logic can stay simple: iterate through the list, add the relevant fields, and keep the most recent ending balance. The second idea is user-facing conclusion. Good command-line tools do not simply stop after raw output; they explain the result in a short, readable message.
This step combines the record-processing techniques from earlier tasks with the user-facing reporting completed at the end of the application.
Key terminology:
- Aggregation: Combining many detailed values into totals or summary statistics.
- Ending balance: The balance stored in the final monthly record.
- Dictionary: A Python data structure that stores named values under keys.
- Remaining gap: The difference between the target amount and the current ending balance.
What you'll accomplish:
- Aggregate the monthly record list into totals and final balance information.
- Print a closing summary that reflects either success or remaining progress.
- Finish the savings goal simulator as a complete command-line tool. ### Context
The projection has already produced a list of monthly records. In this task, you'll transform that detailed history into a compact summary containing totals and the final balance. This summary will later be used to generate the application's closing report.
Concepts
As the program processes each record, it updates running totals for deposits and interest. It also keeps track of the most recent ending balance.
Returning a dictionary is a convenient way to package related summary values under descriptive keys such as
Once the summary data exists, the last improvement is communication. The CLI should end with a clear message that helps the user interpret the totals, whether the goal was reached or there is still progress to make.months,total_deposited,total_interest, andending_balance.Concepts
Conditional output is a common use of
ifstatements: one branch handles the goal-reached case and another handles the still-working-toward-the-goal case.Formatting values with
:.2fkeeps the totals consistent with earlier output and avoids distracting floating-point precision in the final report.When calculating the remaining amount needed to reach a goal, it is often helpful to guard against negative values. A function such as
max(..., 0.0)can ensure that a remaining amount never displays below zero. You finished the last feature of the application. The simulator can now collect user inputs, calculate monthly growth, store each month's result in a list, stop early when the target is reached, and print both detailed and summary output. ### Wrap-upYou built a complete Python command-line savings goal simulator using core language features: numeric conversion, functions, loops, lists, conditional logic, and formatted output.
The simulator can now collect user input, project monthly savings growth, stop early when the goal is reached, and print a final progress summary.
As a next step, try extending the program with input validation, alternative compounding schedules, or file-based export of the monthly records. You could also refactor the record structure from nested lists to dictionaries or data classes once you are comfortable with those features.
About the author
Real skill practice before real-world application
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Learn by doing
Engage hands-on with the tools and technologies you’re learning. You pick the skill, we provide the credentials and environment.
Follow your guide
All labs have detailed instructions and objectives, guiding you through the learning process and ensuring you understand every step.
Turn time into mastery
On average, you retain 75% more of your learning if you take time to practice. Hands-on labs set you up for success to make those skills stick.