Return to Abstraction Hub

🍷 Welcome to VINO PH — A Python Learning Journey

This page presents a complete, production-quality Python program for a Philippine wine shop ordering system called VINO PH. Whether you are a beginner programmer in the Philippines, a student learning Python fundamentals, or a developer revisiting the foundations, this walkthrough is designed to guide you — line by line — through one of the most practical introductory Python programs you can build.

VINO PH demonstrates several core Python concepts: how to model real-world data using nested dictionaries, how to display formatted menus with f-strings and format specifiers, how to handle unpredictable user input using while True loops with try/except exception handling, and how to compute and display a formatted receipt. Each concept is introduced in the context of a real, working program — not just isolated code snippets — so you can see why each design decision was made, not just what the code does.

By the end of this walkthrough, you will understand not just the code, but the thinking behind the code — the kind of logical reasoning that separates a beginner who writes code from a developer who engineers solutions.

🐍
Language
Python 3
📦
Concepts
7 Core Topics
🍾
Wines in Menu
15 Selections
🇵🇭
Market
Philippines (PHP)
🍷 Python Source Code & Explanation

VINO PH Wine Shop
Program Walkthrough

A complete logical breakdown of the Python script — every line explained, step by step.

Full Source
Complete Python Script
wine_shop.py
# ── VINO PH — Wine Shop (Philippines) ──
# Python 3 · by Glenn Pansensoy · Valleys & Bytes

wines = {
    1:  {"name": "Yellow Tail Cabernet Sauvignon (Australia)",          "price": 799},
    2:  {"name": "Jacob's Creek Shiraz (Australia)",                   "price": 899},
    3:  {"name": "Concha y Toro Frontera Cabernet Sauvignon (Chile)",   "price": 599},
    4:  {"name": "Beringer Founders' Estate Merlot (USA)",             "price": 1299},
    5:  {"name": "Robert Mondavi Private Selection Chardonnay (USA)",  "price": 1499},
    6:  {"name": "Gallo Family Vineyards Merlot (USA)",               "price": 649},
    7:  {"name": "Sutter Home Cabernet Sauvignon (USA)",              "price": 699},
    8:  {"name": "Lindemans Bin 65 Chardonnay (Australia)",           "price": 899},
    9:  {"name": "Penfolds Koonunga Hill Shiraz Cabernet (Australia)", "price": 1199},
    10: {"name": "Wolf Blass Yellow Label Cabernet Sauvignon",        "price": 1099},
    11: {"name": "Hardys Stamp Shiraz Cabernet (Australia)",          "price": 799},
    12: {"name": "Oxford Landing Cabernet Sauvignon (Australia)",     "price": 749},
    13: {"name": "Woodbridge by Robert Mondavi Cabernet (USA)",      "price": 999},
    14: {"name": "Kim Crawford Sauvignon Blanc (New Zealand)",       "price": 1699},
    15: {"name": "Oyster Bay Sauvignon Blanc (New Zealand)",         "price": 1499},
}

# ── Welcome banner ──
print("==================================================")
print("     WELCOME TO VINO PH - Wine Shop (Philippines)")
print("     Available Wines (Prices in PHP per bottle)")
print("==================================================")

# ── Display the menu via for loop ──
for num, wine in wines.items():
    print(f"{num:2d}. {wine['name']:50} ₱{wine['price']:,.0f}")

# ── First input loop: wine selection ──
while True:
    try:
        choice = int(input("\nEnter the number of the wine you want to buy (1-15): "))
        if choice in wines:
            selected_wine = wines[choice]
            print(f"\nYou selected: {selected_wine['name']}")
            print(f"Price per bottle: ₱{selected_wine['price']:,}")
            break
        else:
            print("Invalid number! Please choose between 1 and 15.")
    except ValueError:
        print("Please enter a valid number!")

# ── Second input loop: quantity ──
while True:
    try:
        quantity = int(input("\nEnter quantity (bottles): "))
        if quantity > 0:
            break
        else:
            print("Quantity must be at least 1!")
    except ValueError:
        print("Please enter a valid number!")

# ── Computation ──
total_cost = selected_wine['price'] * quantity

# ── Print receipt ──
print(f"Wine          : {selected_wine['name']}")
print(f"Price per bottle: ₱{selected_wine['price']:,}")
print(f"Quantity      : {quantity}")
print(f"Total Cost    : ₱{total_cost:,}")
print("Thank you for shopping at VINO PH! 🍷")
Logical Breakdown
Step-by-Step Explanation
01

The Wine Inventory — Dictionary Data Structure

Data Structure
Code Snippet
wines = {
    1: {"name": "Yellow Tail Cabernet Sauvignon", "price": 799},
    2: {"name": "Jacob's Creek Shiraz", "price": 899},
    ... (15 items total)
}
Why was this code used?
A dictionary (dict) is the ideal Python data structure when you need to look up values by a key. Here, each wine number (1–15) is a key, and each value is another dictionary containing the wine's name and price. This creates a nested dictionary — a dictionary inside a dictionary.
What is its significance?
It acts as the program's database — the single source of truth for all product information. Instead of scattering 15 wine names and prices across dozens of variables, everything is organized in one place. Adding a new wine is as simple as adding one more entry.
How does it operate?
When the user types a number (e.g. 5), the program uses it as a key: wines[5] instantly returns {"name": "Robert Mondavi...", "price": 1499}. No looping required — dictionary lookup is O(1) — instant access regardless of how many wines exist.
dict { } nested dict key-value pairs O(1) lookup
02

Welcome Banner — print() Statements

Output / UI
Code Snippet
print("==================================================")
print("     WELCOME TO VINO PH - Wine Shop (Philippines)")
print("     Available Wines (Prices in PHP per bottle)")
print("==================================================")
Why was this code used?
print() is Python's built-in function for displaying text output to the terminal. Multiple calls construct a visual banner that greets the user, establishes the shop's identity, and sets context before showing products.
What is its significance?
This is the program's user interface header. The rows of = signs create a visual border — a classic terminal UI technique mimicking a real shop menu or POS system.
How does it operate?
Python executes print() statements sequentially from top to bottom. Each call outputs one line followed by a newline character. The strings are string literals displayed exactly as written.
print() string literals sequential execution terminal UI
03

Displaying the Menu — for Loop with f-strings

Iteration / Formatting
Code Snippet
for num, wine in wines.items():
    print(f"{num:2d}. {wine['name']:50} ₱{wine['price']:,.0f}")
Why was this code used?
A for loop with .items() efficiently iterates over every wine in the dictionary without repeating code. Writing 15 individual print() calls would be tedious. The loop handles all 15 wines with just 2 lines.
What is the significance of f-strings and format specs?
f-strings allow Python variables to be embedded directly inside a string using {} braces. The format specifiers control column widths and number display:

{num:2d} — integer, at least 2 characters wide
{wine['name']:50} — string padded to 50 characters
{wine['price']:,.0f} — float with commas, 0 decimal places
How does .items() operate?
wines.items() returns each key-value pair as a tuple. The for num, wine in syntax unpacks each tuple — num gets the integer key and wine gets the nested dictionary. This is called tuple unpacking.
for loop .items() f-string format specifier :2d :50 :,.0f tuple unpacking
04

Wine Selection Loop — while True + try/except

Input Validation
Code Snippet
while True:
    try:
        choice = int(input("\nEnter the number of the wine (1-15): "))
        if choice in wines:
            selected_wine = wines[choice]
            break
        else:
            print("Invalid number! Please choose between 1 and 15.")
    except ValueError:
        print("Please enter a valid number!")
Why while True?
while True creates an infinite loop that runs until explicitly stopped with break. This pattern guarantees the program never proceeds with invalid input — it keeps asking until the user provides a valid response.
Why try / except ValueError?
input() always returns a string. Wrapping it in int() converts it to an integer — but if the user types "abc", int() raises a ValueError. The try/except block catches that crash and prints a friendly message instead.
What does "choice in wines" check?
The in operator checks if the value exists as a key in the wines dictionary. Returns True only for 1–15 — this is a range and existence check combined into one clean operation.
while True try / except ValueError int(input()) in operator break
05

Quantity Input Loop — Positive Integer Validation

Input Validation
Code Snippet
while True:
    try:
        quantity = int(input("\nEnter quantity (bottles): "))
        if quantity > 0:
            break
        else:
            print("Quantity must be at least 1!")
    except ValueError:
        print("Please enter a valid number!")
Why is this loop separate from the wine selection loop?
Each loop has a single responsibility — a core principle of clean code. The first loop handles which wine, this loop handles how many. Separating them keeps logic clear, easier to debug, and easier to modify independently.
Why is the condition quantity > 0 instead of quantity >= 1?
Both are mathematically equivalent for integers. The > form reads more naturally as "Must be a positive number." It also explicitly rejects zero, negative numbers, and text — all invalid purchase quantities.
What is the function of break here?
break immediately exits the innermost while loop. Without it, the loop would run forever even after getting valid input. Think of break as the exit door of the loop.
while True quantity > 0 break single responsibility
06

Total Cost Computation — Arithmetic Expression

Calculation
Code Snippet
total_cost = selected_wine['price'] * quantity
Why was this placed after both loops?
The calculation only happens once, after both values are guaranteed valid. Placing it inside a loop would compute the total on every iteration — wasteful and incorrect. By computing it here, both values are certain to be correct integers.
How does selected_wine['price'] work?
selected_wine is a reference to the inner dictionary (e.g. {"name": "Kim Crawford...", "price": 1699}). Using ['price'] accesses the integer stored at that key — the result is then multiplied by quantity.
What is the significance of storing it in total_cost?
Storing the result in a named variable avoids recalculating multiple times. It also makes the code self-documenting — the name immediately communicates what the value represents.
arithmetic operator * dict key access ['price'] variable assignment
07

Receipt Output — f-strings with Number Formatting

Final Output
Code Snippet
print(f"Wine          : {selected_wine['name']}")
print(f"Price per bottle: ₱{selected_wine['price']:,}")
print(f"Quantity      : {quantity}")
print(f"Total Cost    : ₱{total_cost:,}")
print("Thank you for shopping at VINO PH! 🍷")
Why use f-strings again here?
The receipt must display dynamic values — the actual wine chosen, the real price, the user's quantity, and the computed total. f-strings are the cleanest way to embed Python variable values into output text. The :, format spec adds thousands separators (e.g. 16991,699) for currency readability.
What is the significance of the receipt format?
The padded label alignment creates a tabular, receipt-style layout — all colons line up vertically. This is a visual choice that improves readability, mimicking a real-world POS receipt common in Philippine retail shops.
How does ₱{total_cost:,} format large numbers?
The :, format specifier instructs Python to insert commas every 3 digits. So 16990 becomes ₱16,990 automatically — no manual string manipulation required. The symbol is a Unicode character typed directly into the string.
f-string :, comma separator ₱ Unicode symbol receipt formatting dynamic output

📚 Deep Dive: Key Python Concepts Explained

Understanding VINO PH means understanding the building blocks it is composed of. Below is a deeper exploration of the most important Python concepts in this program — written for learners who want to go beyond surface-level understanding and truly internalize why Python works the way it does.

Nested Dictionaries as Mini-Databases. In professional software, data is usually stored in a database. In a small Python program, a nested dictionary serves exactly the same purpose. The outer dictionary's keys (integers 1–15) act like row IDs. The inner dictionaries act like rows in a table, each containing a name column and a price column. This is the same mental model used in SQL, MongoDB, and most modern data systems.

The Defensive Input Pattern. The combination of while True + try/except + break is one of the most important patterns in Python programming. It is called defensive programming — you assume the user will make mistakes and design your code to handle them gracefully without crashing. This same pattern is used in production-level command-line tools, system scripts, and automation code all over the world.

f-strings vs Older String Formatting. Python has had three string formatting methods: the old % operator, the .format() method, and modern f-strings (introduced in Python 3.6). f-strings are now the preferred method because they are readable, concise, and support format specifiers directly inside the curly braces. VINO PH uses advanced format specs like :2d, :50, and :,.0f — knowing how to read these is an important skill for any Python developer.

💡 Pro Tip for Students

Try extending this program: add a discount system (if quantity >= 5: discount = 0.10), a cart system that allows multiple purchases, or export the receipt to a .txt file using open("receipt.txt", "w"). These extensions will solidify every concept you learned here.

⭐ Python Best Practices Demonstrated in VINO PH

VINO PH is not just a working program — it is a demonstration of clean, professional coding habits. Here are the specific best practices it models that you should carry into every program you write:

🎓 Learning Roadmap

After mastering this program, your next steps in Python should be: functions and modules → file I/O → object-oriented programming (classes) → working with APIs → databases with SQLite or PostgreSQL. Each step builds directly on what you learned here.

Concepts Used at a Glance
Concept Python Syntax Purpose in This Program
Nested Dictionarywines = {1: {"name":..., "price":...}}Stores all 15 wines and their prices as a structured database
print()print("text")Displays banner, menu, confirmations, and receipt to the user
for loop + .items()for num, wine in wines.items():Iterates and prints all 15 wines without repeating code
f-string formattingf"{num:2d}. {name:50} ₱{price:,.0f}"Formats menu and receipt output with aligned columns and commas
Infinite loopwhile True:Keeps asking for input until the user enters a valid response
Exception handlingtry: ... except ValueError:Prevents crashes when user types non-numeric input
Type conversionint(input(...))Converts the string returned by input() into a usable integer
Membership testif choice in wines:Validates that the user's number matches an actual wine key (1–15)
break statementbreakExits the while loop once valid input is confirmed
Arithmetictotal_cost = price * quantityComputes the final purchase total after both inputs are gathered

🔗 Share This Article

Found this walkthrough helpful? Share it with fellow Python learners, students, and developers!


👤 Follow Glenn Pansensoy

Stay connected for more Python tutorials, code walkthroughs, and tech content from Valleys & Bytes.

💬 Comments

Have a question, correction, or insight? Leave a comment below — all feedback is welcome!


✅ Your comment has been submitted! It will appear after moderation.
M
Maria Santos
March 10, 2026 · 09:14 AM
This is exactly what I needed for my Python class! The explanation of the while True + try/except pattern finally clicked for me. Salamat po, Glenn!
J
Jose Reyes
March 11, 2026 · 02:37 PM
The O(1) dictionary lookup explanation is gold! Most beginner tutorials just show you how to use dicts without explaining the performance advantage. This actually builds real understanding.
A
Ana Lim
March 12, 2026 · 08:50 AM
I tried extending this with a cart feature like you suggested in the tip box. It took me 3 hours but I finally got it working! The single responsibility principle really helped me structure the new loops.

📬 Subscribe to Valleys & Bytes

Get notified when new Python tutorials, code walkthroughs, and tech articles are published. No spam — ever.

🐍 Python Tutorials 💻 Code Walkthroughs 🇵🇭 PH Tech Content 🔔 New Article Alerts 🎓 Beginner-Friendly
🎉 You're subscribed! Welcome to Valleys & Bytes.

🔒 Your email is safe. Unsubscribe anytime. No spam, ever.

🍷

You've Mastered VINO PH

Congratulations on completing this walkthrough. You have now seen not just a working Python program, but the thinking process behind every design choice — from the nested dictionary as a mini-database, to the defensive input pattern, to the receipt formatting that mirrors a real Philippine POS system.

This is what separates a programmer who copies code from a developer who understands it. You now understand it. Every concept in VINO PH — dictionaries, loops, exception handling, f-strings, arithmetic — appears in real-world Python projects every single day, from simple scripts to enterprise applications.

"Programs must be written for people to read, and only incidentally for machines to execute." — Harold Abelson, Structure and Interpretation of Computer Programs

Keep building. Keep breaking things. Keep reading. The best programmers never stop being curious — and you are already on the right path.

🐍 Review the Code Again