VINO PH β
Interactive Python Wine Shop
Run Live in Your Browser
A complete Python wine ordering system that runs live in your browser. No installation needed. Click "Run Program" below to start the interactive experience.
Every line is explained step by step β from nested dictionaries to defensive input validation. Learn by doing.
VINO PH: A Python Learning Journey
π· Welcome to VINO PH
This page presents a complete, production-quality Python program for a Philippine wine shop ordering system called VINO PH. It demonstrates core Python concepts: nested dictionaries as a mini-database, f-strings with format specifiers for clean output, while True loops with try/except for robust input validation, arithmetic computation, and a senior citizen discount feature.
Every concept is introduced in the context of a real, working program β so you see why each design decision was made. By the end, you'll understand not just the code, but the thinking behind the code.
VINO PH is intentionally small enough to read in one sitting, yet it packs in almost every
pattern a beginner will meet again and again in bigger, real-world systems: a data layer
(the wines dictionary), a presentation layer (the formatted menu and receipt),
a validation layer (the two while True loops), and a business-rules layer (the
senior discount calculation). Professional applications β a point-of-sale system, an e-commerce
checkout, a booking engine β are built from the exact same four layers, just at a much larger
scale. Learning to recognize this shape in a 70-line script is what makes it possible to
recognize it later inside a 70,000-line codebase.
Run VINO PH in Your Browser
Click "Run Program" to start the VINO PH wine shop. The program runs entirely in your browser using Pyodide β Python compiled to WebAssembly. Type your responses directly in the terminal. Senior citizens get a 10% discount!
On a phone keyboard, tap Send (or the paper-plane button) if the Return/Go key doesn't submit your answer.
Complete Python Script
# ββ VINO PH β Wine Shop (Philippines) ββ # Python 3 Β· Interactive Β· Poetic 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!") # ββ Senior Citizen Discount ββ is_senior = input("\nAre you a senior citizen? (yes/no): ").strip().lower() discount_rate = 0.10 if is_senior == "yes" else 0.00 # ββ Computation ββ total_cost = selected_wine['price'] * quantity discount_amount = total_cost * discount_rate final_cost = total_cost - discount_amount # ββ Print receipt ββ print("\n" + "=" * 50) print(" VINO PH - RECEIPT") print("=" * 50) print(f"Wine : {selected_wine['name']}") print(f"Price per bottle: β±{selected_wine['price']:,.0f}") print(f"Quantity : {quantity}") print(f"Subtotal : β±{total_cost:,.0f}") if discount_amount > 0: print(f"Senior Discount (10%): -β±{discount_amount:,.0f}") print(f"Total Cost : β±{final_cost:,.0f}") print("=" * 50) print("Thank you for shopping at VINO PH! π·")
Step-by-Step Explanation
The Wine Inventory β Dictionary Data Structure
Data Structure βΎwines = { 1: {"name": "Yellow Tail Cabernet Sauvignon", "price": 799}, 2: {"name": "Jacob's Creek Shiraz", "price": 899}, ... (15 items total) }
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.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.Welcome Banner β print() Statements
Output / UI βΎprint("==================================================") print(" WELCOME TO VINO PH - Wine Shop (Philippines)") print(" Available Wines (Prices in PHP per bottle)") print("==================================================")
print() is Python's built-in function for displaying text output to the terminal. Multiple calls construct a visual banner that greets the user and sets context.= signs create a visual border β a classic terminal UI technique.Displaying the Menu β for Loop with f-strings
Iteration / Formatting βΎfor num, wine in wines.items(): print(f"{num:2d}. {wine['name']:50} β±{wine['price']:,.0f}")
for loop with .items() efficiently iterates over every wine in the dictionary without repeating code.{} braces. 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
Wine Selection Loop β while True + try/except
Input Validation βΎ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!")
while True creates an infinite loop that runs until explicitly stopped with break. This pattern guarantees the program never proceeds with invalid input.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.selected_wine being valid, so this loop is the gatekeeper for everything that follows.Quantity Input Loop β Positive Integer Validation
Input Validation βΎ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!")
> form reads more naturally as "Must be a positive number." It explicitly rejects zero, negative numbers, and text.total_cost = price * quantity would print a nonsensical or negative subtotal. Rejecting bad quantities here keeps every number in the receipt trustworthy.Senior Citizen Discount & Total Cost Computation
Calculation βΎis_senior = input("\nAre you a senior citizen? (yes/no): ").strip().lower() discount_rate = 0.10 if is_senior == "yes" else 0.00 total_cost = selected_wine['price'] * quantity discount_amount = total_cost * discount_rate final_cost = total_cost - discount_amount
0.10 if is_senior == "yes" else 0.00 sets the discount rate to 10% for seniors and 0% otherwise in one clear line.total_cost is the product of price and quantity. Second, discount_amount is the total multiplied by the rate. Third, final_cost subtracts the discount from the total..strip() removes accidental leading/trailing spaces and .lower() normalizes the answer, so "Yes", " YES ", and "yes" are all treated identically. Without it, a stray space or capital letter would silently deny a senior their discount.Receipt Output β f-strings with Number Formatting
Final Output βΎprint("\n" + "=" * 50) print(" VINO PH - RECEIPT") print("=" * 50) print(f"Wine : {selected_wine['name']}") print(f"Price per bottle: β±{selected_wine['price']:,.0f}") print(f"Quantity : {quantity}") print(f"Subtotal : β±{total_cost:,.0f}") if discount_amount > 0: print(f"Senior Discount (10%): -β±{discount_amount:,.0f}") print(f"Total Cost : β±{final_cost:,.0f}") print("=" * 50) print("Thank you for shopping at VINO PH! π·")
:, format spec adds thousands separators (e.g. 1699 β 1,699) for currency readability.if discount_amount > 0: check ensures the discount line only appears when a discount was actually applied.Key Python Concepts Explained
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.
f-strings vs Older String Formatting. f-strings (introduced in Python 3.6) 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.
π‘ Pro Tip: 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").
Why Every Programmer Should Learn This
π― It's Not About Wine β It's About Reliable Software
VINO PH looks like a small toy program, but the seven patterns inside it are the same seven patterns that show up in payroll systems, hospital scheduling software, banking apps, and e-commerce checkouts. A nested dictionary today, a full SQL table tomorrow. A while True + try/except loop today, a production form-validation layer tomorrow. Programmers who skip learning these fundamentals "because the real work uses frameworks" often struggle later, because every framework is ultimately built on top of these exact primitives.
There is also a quieter, more important lesson here: defensive programming
is a form of respect for the user. The two while True loops in VINO PH exist
so that a customer who fat-fingers a "6" as an "e" never sees a crash, a stack trace, or a lost
order. Learning to anticipate human error β rather than assuming perfect input β is what
separates code that works in a demo from code that survives contact with real people.
π€ VINO PH in the Era of AI
It is tempting to think that in the age of AI coding assistants, understanding a program like VINO PH line-by-line is optional β that you can simply ask an AI to "write me a wine shop program" and move on. The opposite is true. AI tools like Claude are extremely good at generating code such as this, but they cannot substitute for a human who can read, verify, and reason about the code that gets generated. When an AI-written program produces a wrong total, silently swallows an exception, or applies a discount to the wrong customer, someone still has to trace the bug back through the dictionary lookups, the loops, and the arithmetic β exactly the skill this walkthrough builds.
In practice, the programmers who benefit most from AI assistance are the ones who already
understand fundamentals like these. They can spot when generated code has an off-by-one error
in {num:2d}, notice when a try/except block is silently hiding a real
bug, or recognize when a "senior discount" conditional expression has its logic backwards.
Fluency in fundamentals is what turns an AI from an autocomplete tool into a
genuine collaborator β you direct it, review it, and correct it, rather than trusting it blindly.
Concepts Used at a Glance
| Concept | Python Syntax | Purpose in This Program |
|---|---|---|
| Nested Dictionary | wines = {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 formatting | f"{num:2d}. {name:50} β±{price:,.0f}" | Formats menu and receipt output with aligned columns and commas |
| Infinite loop | while True: | Keeps asking for input until the user enters a valid response |
| Exception handling | try: ... except ValueError: | Prevents crashes when user types non-numeric input |
| Type conversion | int(input(...)) | Converts the string returned by input() into a usable integer |
| Membership test | if choice in wines: | Validates that the user's number matches an actual wine key (1β15) |
| break statement | break | Exits the while loop once valid input is confirmed |
| Conditional expression | 0.10 if is_senior == "yes" else 0.00 | Sets discount rate based on senior citizen status |
| Arithmetic | total_cost = price * quantity | Computes the final purchase total after all inputs are gathered |
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.
π Join 8,400+ developers. Your email is never shared or sold.
You've Mastered VINO PH
π What You've Accomplished
Congratulations! You've 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. You even ran it live in your browser!
This is what separates a programmer who copies code from a developer who understands it. Every concept in VINO PH β dictionaries, loops, exception handling, f-strings, arithmetic β appears in real-world Python projects every single day.