Python Tutorial · Beginner Friendly

Vegetable Shop —
Full Python Source Code
Line by Line

A complete command-line vegetable ordering system built from scratch — and pulled apart line by line so every piece of logic is crystal clear. Whether you're a beginner meeting Python for the first time or an experienced dev who wants a crisp refresher, this is the tutorial for you.

📅 March 7, 2026 ⏱ 20 min read 🎓 Beginner 🐍 Python 3
Return to Encapsulation Hub

What You'll Build

📘 A Hands-On Python Project

This vegetable shop program is a complete command-line application that demonstrates core Python concepts in a practical, real-world context. You'll build a working ordering system that displays inventory, collects customer input, validates data, and prints a formatted receipt — all in under 100 lines of code.

While the program is procedural (using functions, dictionaries, and loops), it embodies the same encapsulation principles you'll find in professional object-oriented code. The main() function acts as a capsule that contains all program logic, variables are local and protected from external access, and data flows through controlled interfaces.

Every code example in this guide is fully interactive — you can copy and run the program right in your browser using the JavaScript terminal simulation. No setup required.

11 step-by-step explanations 5 knowledge-check questions Live browser-based terminal Full source code with syntax highlighting Visual program flow diagram

Why This Program?

This humble Python script is a perfect starting point for understanding how real programs work. It demonstrates:

  • Dictionaries — storing and looking up data
  • Loops — iterating over items and handling user input
  • Functions — structuring code into reusable blocks
  • Error Handling — preventing crashes with try/except
  • Input/Output — interacting with the user via the terminal
  • String Formatting — creating clean, readable output

Key Insight: This program is fully encapsulated — all data and logic live inside a single function (main()), and the program only runs when explicitly called. This is the same principle that powers professional Python applications.

What You'll Learn

By the end of this tutorial, you'll understand:

  • How to define a main() function as the program's entry point
  • How to use a dictionary as a pricing table
  • How to loop through dictionary items with for
  • How to validate user input with while True and try/except
  • How to accumulate a running total
  • How to format a receipt with f-strings
  • The if __name__ == "__main__" guard pattern

vegetable_shop.py

Here's the complete program. Every line is explained in the steps below. Copy it, run it, and modify it — this is your code now.

vegetable_shop.py
def main():
    prices = {
        "Eggplant (Talong)": 80,
        "Tomatoes":          120,
        "Potatoes":          140,
        "Onions":            160,
        "Garlic":            180,
        "Pechay":            80,
        "Broccoli":          170,
        "Carrots":           160,
        "Radish (Labanos)":  80,
        "Alugbati":          60,
        "Kangkong":          50,
        "Cabbage":           150
    }

    order = {}

    print("════════════════════════════════════════════")
    print("       WELCOME TO THE VEGETABLE SHOP        ")
    print("════════════════════════════════════════════")

    print(f"{'Item Name':<25} {'Price per kg':>15}")
    print("-" * 42)
    for veg, price in prices.items():
        print(f"{veg:<25} ₱{price:>14.2f}")
    print("-" * 42)

    print("\nINSTRUCTIONS:")
    print("• Enter quantity in kg (e.g., 0.5, 2, 1.25)")
    print("• Press Enter to skip an item")
    print("• Type 'DONE' at any time to finish and pay\n")

    for vegetable, price in prices.items():
        while True:
            try:
                user_input = input(f"How many kg of {vegetable}? ").strip().lower()

                if user_input == "done":
                    break
                if user_input == "":
                    qty = 0.0
                    break

                qty = float(user_input)
                if qty < 0:
                    print("Quantity cannot be negative.")
                    continue
                break
            except ValueError:
                print("Invalid input. Please enter a number or 'done'.")

        if 'user_input' in locals() and user_input == "done":
            break

        if qty > 0:
            order[vegetable] = qty

    if not order:
        print("\nNo items selected. Have a nice day!")
        return

    print("\n" + "="*60)
    print("FINAL RECEIPT".center(60))
    print("="*60)
    print(f"{'Vegetable':<20} {'Qty (kg)':>10} {'Unit Price':>12} {'Subtotal':>12}")
    print("-" * 60)

    total = 0.0
    for veg, qty in order.items():
        subtotal = qty * prices[veg]
        total += subtotal
        print(f"{veg:<20} {qty:>10.2f} {prices[veg]:>12.2f} {subtotal:>12.2f}")

    print("-" * 60)
    print(f"{'TOTAL AMOUNT DUE':<44} ₱{total:>11.2f}")
    print("="*60)
    print("\nThank you for shopping with us!")


if __name__ == "__main__":
    main()

Every Line Explained

Each step below breaks down a distinct part of the program. Click the filters to group by theme.

01
Defining main()
def main():
function · structure

A function definition wraps all program logic under a single named block. Encapsulating everything inside main() keeps variables out of global scope, prevents accidental side effects on import, and makes the code easy to test in isolation.

Think of it as the engine — nothing runs until main() is explicitly called at the very bottom of the file.

02
The prices Dictionary
prices = { "Tomatoes": 120, ... }
dict · data store

A Python dictionary stores key-value pairs. Each vegetable name (the key) maps to its price per kg (the value). Dictionaries allow instant O(1) lookup — prices["Garlic"] returns 180 without scanning the entire collection.

This is the program's single source of truth for all pricing. Updating a price means changing exactly one number in one place.

03
Empty order Dictionary
order = {}
dict · accumulator

An empty dictionary initialised to collect the customer's selections as the program runs. As quantities are entered it grows dynamically: order["Tomatoes"] = 1.5.

Only items with qty > 0 are ever stored, so the final receipt stays clean — no zero-quantity rows cluttering the output.

04
Banner & Inventory Table
print(f"{'Item Name':<25} ...")
f-string · formatting

F-strings with alignment specifiers produce a neat, readable price table before any ordering begins — so customers know what's available and what it costs.

SpecifierMeaning
:<25Left-align, pad to 25 chars
:>14.2fRight-align float, 2 decimals
"–" * 42Repeats a separator line
05
Nested for + while Loops
for vegetable, price in prices.items():
loop · iteration

The for loop visits each vegetable exactly once, in order. The inner while True loop keeps re-asking the same question until the user provides valid input — it can only escape via break.

.strip().lower() normalises the raw input so "DONE", "Done", and "done" are all treated identically.

06
try / except Error Handling
except ValueError:
exception handling · safety

Calling float("abc") raises a ValueError that would crash an unprotected program. The try/except block intercepts it and prints a helpful message instead of terminating.

KeywordWhat it does
continueSkips back to top of while loop
breakExits the current loop level
07
"done" Two-Level Exit
if user_input == "done": break × 2
control flow · nested break

A single break only exits one loop level. Because the loops are nested, two strategically placed break statements are needed — the first escapes the while loop, the second escapes the for loop.

'user_input' in locals() is a defensive guard ensuring the variable exists before it's read, preventing a NameError on first iteration.

08
Storing Valid Orders
if qty > 0: order[vegetable] = qty
conditional · filtering

Skipped items (Enter pressed) default to qty = 0.0. The if qty > 0 guard ensures only genuinely ordered vegetables are added to the order dictionary.

This keeps the receipt accurate and uncluttered — a small condition with a big impact on the final output's quality.

09
Empty Order Early Exit
if not order: return
defensive programming · guard clause

not order evaluates to True when the dictionary is empty. The return statement exits the function immediately, preventing the receipt section from running with no data to display.

This is called a guard clause — a clean pattern that handles edge cases at the top rather than nesting them inside the main logic.

10
Receipt & Running Total
total += subtotal
accumulator pattern · arithmetic

total starts at 0.0. Each iteration computes subtotal = qty × price and adds it to the running total — the classic accumulator pattern.

prices[veg] cross-references the original prices dictionary by name, since order only stores quantities. Two dictionaries working as one system.

11
The __main__ Guard
if __name__ == "__main__": main()
module guard · Python idiom

When this file is run directly, Python sets __name__ to "__main__" and main() is called. When it's imported by another script, __name__ equals the filename — so main() is silently skipped.

This is a universal Python best practice that makes every script both safely importable as a module and directly runnable as a program.

Run the Program in Your Browser

This is a fully functional JavaScript simulation of the Python program. Enter quantities, type done to finish early, press Enter to skip — it behaves exactly like the real script.

vegetable_shop.py — interactive
Click to launch the vegetable shop

How the Program Executes

Follow the execution path from start to finish. This visual flow shows exactly how control moves through the program.

🔀 Execution Path — Top to Bottom
START → define prices dict & empty order dict
Print welcome banner & full inventory price table
for each vegetable in prices.items()
while True → ask "How many kg of {vegetable}?"
"done" typed
→ break × 2
exit both loops
Invalid input
→ print error
→ retry (continue)
qty < 0
→ print warning
→ retry (continue)
Valid qty > 0
→ store in order
→ next vegetable
if not order → print "No items selected" → return early
for each item in order → compute subtotal → accumulate total
Print formatted receipt with all subtotals
Print grand total (₱ total)
END → "Thank you for shopping with us!" ✓

Python Basics Cheat Sheet

Everything you need to remember from this tutorial — bookmark this for quick reference.

📚 Data Structures

StructureUse
dictKey-value pairs, O(1) lookup
listOrdered, mutable sequence
tupleImmutable sequence
setUnique, unordered items

🔄 Control Flow

KeywordEffect
breakExit the current loop
continueSkip to next iteration
returnExit function
passPlaceholder, do nothing

✨ f-String Formatting

SyntaxResult
{var:<10}Left-align, pad to 10
{var:>10}Right-align, pad to 10
{var:.2f}Float with 2 decimals
{var:^20}Center-align, pad to 20

🐍 Python Idioms

PatternPurpose
if __name__ == "__main__":Run only when executed directly
if not list:Check if list/dict is empty
try/exceptGraceful error handling
with open() as f:Safe file handling

Quick Knowledge Check

Reinforce what you've learned about Python fundamentals and program structure.

0/5

Review any missed questions above.

Spread the Knowledge

Comments

Leave a Comment

Sort by:

Subscribe to Poetic Bytes

Level up your Python knowledge.

In-depth Python tutorials, AI insights, and software engineering guides — delivered straight to your inbox. No spam, ever.

Weekly Python tutorials AI & ML deep-dives OOP series updates Free, cancel anytime

🔒 Join 8,400+ developers. Your email is never shared or sold.

Follow Poetic Bytes

Stay connected across every platform. Get daily Python tips, OOP insights, and the latest AI developments — wherever you spend your time online.