1. Home
  2. Encapsulation Hub
  3. Vegetable Shop Tutorial
Return to Encapsulation Hub

Where code meets curiosity

Valleys & Bytes

A Python tutorial blog exploring comprehensive PYTHON programming methods, algorithms, and the culture of contemporary coding to keep pace with the fast-moving AI technology. Deep dives for developers — from beginner Python projects to advanced programming concepts.OOP programming is the DNA of AI.

A signal in
the digital noise.

"We live between the valleys of human thought and the bytes of machine logic — this is where I write."

Valleys & Bytes is an independent technology publication dedicated to exploring the intersections of software engineering, computational thinking, and the culture surrounding the machines we build. Founded in 2023, this space was born out of a conviction that technical writing doesn't have to be dry — it can be poetic, provocative, and precise all at once.

Every article here is a deep-dive: no shallow takes, no engagement-bait. Whether dissecting a sorting algorithm or tracing the philosophy behind open-source software, we commit to the full picture. Pull up a chair. The terminal is always on.

0
Articles Published
0
Monthly Readers
0
Newsletter Subscribers
0
Years Online

Latest from the lab.

🧠

The Quiet Revolution in Automation

Attention mechanisms have reshaped every corner of Automation. I had traced their origins, their math, and what comes next when the context window has no ceiling.

★ Signature Feature · Python · Step-by-Step

The Vegetable Shop
Source Code

This humble Python script is the heart and soul of Valleys & Bytes. 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 article for you.

Python 3 Beginner Friendly 18 min read 11 Concepts Explained
11Concepts Covered
12Vegetables in Menu
~80Lines of Code
1File. No Dependencies.
🥦
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()

Run the program yourself.

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 terminal
Click to launch the vegetable shop

Every line. Every reason. Every detail.

01
Defining the Main Function
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.

How the program executes, 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!" ✓
TIP Use git bisect to binary-search your way to a broken commit in seconds FACT The first computer bug was an actual moth found in a Harvard Mark II relay in 1947 TIP In Python, a, *b, c = [1,2,3,4,5] gives you starred unpacking for free QUOTE "Any fool can write code a computer understands. Good programmers write code humans can understand." — Fowler TIP Use ssh -L for local port forwarding to tunnel traffic securely through a bastion host FACT The Linux kernel has over 27 million lines of code contributed by thousands of developers worldwide TIP console.time('label') and console.timeEnd('label') — free performance profiling in the browser TIP Use git bisect to binary-search your way to a broken commit in seconds FACT The first computer bug was an actual moth found in a Harvard Mark II relay in 1947 TIP In Python, a, *b, c = [1,2,3,4,5] gives you starred unpacking for free QUOTE "Any fool can write code a computer understands. Good programmers write code humans can understand." — Fowler TIP Use ssh -L for local port forwarding to tunnel traffic securely through a bastion host FACT The Linux kernel has over 27 million lines of code contributed by thousands of developers worldwide TIP console.time('label') and console.timeEnd('label') — free performance profiling in the browser
"The best code is the code you don't have to write. The second best is code so clear it reads like a well-argued essay — confident, purposeful, and impossible to misread."
— Valleys & Bytes Editorial Manifesto, Issue #001

Patterns worth memorising.

python
from functools import cache
from typing import Generator

# ── Memoised Fibonacci with generator ──────────────────────
@cache
def fib(n: int) -> int:
    """O(n) time, O(n) space — but only computed once per n."""
    return n if n < 2 else fib(n - 1) + fib(n - 2)

def fib_stream(limit: int) -> Generator[int, None, None]:
    """Lazy infinite stream — pull only what you need."""
    a, b = 0, 1
    while a <= limit:
        yield a
        a, b = b, a + b

# ── Context manager for timing code blocks ──────────────────
from contextlib import contextmanager
import time

@contextmanager
def timer(label: str = "block"):
    start = time.perf_counter()
    try:
        yield
    finally:
        elapsed = time.perf_counter() - start
        print(f"[{label}] {elapsed * 1000:.2f}ms")

# Usage
with timer("fib(35)"):
    result = fib(35)
    print(f"fib(35) = {result}")

first_20 = list(fib_stream(6765))
print(f"First 20 Fibonacci: {first_20}")
rust
// ── Safe concurrent counter using Arc + Mutex ───────────────
use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let counter = Arc::new(Mutex::new(0u64));
    let mut handles = Vec::new();

    for _ in 0..8 {
        let c = Arc::clone(&counter);
        handles.push(thread::spawn(move || {
            for _ in 0..1_000_000 {
                let mut val = c.lock().unwrap();
                *val += 1;
            }
        }));
    }

    for h in handles { h.join().unwrap(); }
    println!("Final count: {}", *counter.lock().unwrap());
    // Always prints 8_000_000 — no data race possible
}

// ── Zero-copy string slicing ──────────────────────────────────
fn first_word(s: &str) -> &str {
    s.split_whitespace().next().unwrap_or("")
}

The returned &str borrows from s — no allocation, no copy.
// The borrow checker guarantees s outlives the slice.
fn demonstrate() {
    let sentence = String::from("valleys and bytes");
    let word = first_word(&sentence); &str into String's buffer
    println!("First word: {word}");
}
javascript
── Observable pattern — reactive state without a framework ──
function createStore(initialState) {
  let state = structuredClone(initialState);
  const listeners = new Set();

  return {
    getState: () => structuredClone(state),

    setState(updater) {
      const next = typeof updater === 'function'
        ? updater(state) : updater;
      state = { ...state, ...next };
      listeners.forEach(fn => fn(state));
    },

    subscribe(fn) {
      listeners.add(fn);
      return () => listeners.delete(fn); // unsubscribe
    }
  };
}

// Usage
const store = createStore({ count: 0, user: null });

const unsubscribe = store.subscribe(state => {
  console.log('State changed:', state);
});

store.setState(s => ({ count: s.count + 1 }));
store.setState({ user: { name: 'Ada' } });
unsubscribe(); // stop listening

// ── Async retry with exponential backoff ──────────────────────
async function withRetry(fn, { retries = 3, base = 300 } = {}) {
  for (let i = 0; i <= retries; i++) {
    try { return await fn(); }
    catch (err) {
      if (i === retries) throw err;
      await new Promise(r => setTimeout(r, base * 2 ** i));
    }
  }
}
sql · postgresql
-- ── Window functions: running totals and rankings ────────────
SELECT
  author,
  title,
  views,
  published_at,

  -- Running total of views per author, ordered by date
  SUM(views) OVER (
    PARTITION BY author
    ORDER BY published_at
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) AS running_views,

  -- Dense rank by views (ties get same rank, no gaps)
  DENSE_RANK() OVER (ORDER BY views DESC) AS popularity_rank,

  -- 3-article rolling average views
  AVG(views) OVER (
    PARTITION BY author
    ORDER BY published_at
    ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
  ) AS rolling_avg_3

FROM   articles
WHERE  published_at >= NOW() - INTERVAL '90 days'
ORDER BY author, published_at;

-- ── Recursive CTE: traverse a tag hierarchy ──────────────────
WITH RECURSIVE tag_tree AS (
  SELECT id, name, parent_id, 0 AS depth
  FROM   tags WHERE parent_id IS NULL
  UNION ALL
  SELECT t.id, t.name, t.parent_id, tt.depth + 1
  FROM   tags t
  JOIN   tag_tree tt ON t.parent_id = tt.id
)
SELECT REPEAT('  ', depth) || name AS hierarchy
FROM   tag_tree ORDER BY depth, name;
bash
#!/usr/bin/env bash
# ── Robust script template with error handling ────────────────
set -euo pipefail          # exit on error, unset var, pipe fail
trap 'cleanup' EXIT INT TERM

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_FILE="${SCRIPT_DIR}/deploy.log"

log() { printf '[%s] %s\n' "$(date +%T)" "$*" | tee -a "$LOG_FILE"; }
die() { log "ERROR: $*"; exit 1; }
cleanup() { log "Script finished."; }

# ── Check dependencies ────────────────────────────────────────
require() {
  for cmd in "$@"; do
    command -v "$cmd" &>/dev/null || die "Required: $cmd not found"
  done
}

require docker kubectl git curl

# ── Parallel execution with job control ───────────────────────
declare -a pids=()
for service in api worker scheduler; do
  docker build -t "app/${service}:${GIT_SHA}" "services/${service}" &
  pids+=("$!")
  log "Building ${service} (PID $!)"
done

for pid in "${pids[@]}"; do
  wait "$pid" || die "Build failed (PID $pid)"
done
log "All services built successfully."

What to adopt, trial,
assess, or avoid.

● Adopt
Bun Runtime
Drop-in Node.js replacement with dramatically faster startup, native TypeScript, and built-in bundler. Production-ready for most workloads.
// runtime · javascript
● Adopt
Zod Schema Validation
TypeScript-first schema validation that co-locates your types and runtime checks. Eliminates an entire class of runtime type bugs.
// typescript · validation
◐ Trial
Gleam Language
A statically typed functional language that compiles to Erlang/JS. Combines the safety of Rust's type system with the concurrency of the BEAM VM.
Language · functional
◐ Trial
Drizzle ORM
Lightweight, type-safe SQL ORM for TypeScript. Unlike Prisma, it generates zero runtime abstraction — just plain SQL with full type inference.
// database · orm
○ Assess
Sovereign AI Models
Self-hosted LLMs via Ollama and llama.cpp are maturing fast. Privacy-first AI pipelines are now feasible for teams with moderate hardware budgets.
// ai · infrastructure
○ Assess
Temporal Workflow Engine
Durable execution framework that survives crashes, retries failures, and makes long-running distributed workflows trivially testable.
// distributed · workflows
✕ Hold
Create React App
Officially unmaintained since 2023. Replaced by Vite, Next.js, Remix, or Astro depending on your needs. There is no reason to start a new project with CRA.
// frontend · deprecated
✕ Hold
Class Components (React)
The React team has moved firmly toward hooks-based functional components. Class components receive no new features and new docs don't mention them.
// react · legacy

Books & papers every
developer should encounter.

01
Designing Data-Intensive Applications
Martin Kleppmann · O'Reilly, 2017
Book
02
Attention Is All You Need
Vaswani et al. · NeurIPS, 2017
Paper
03
The Philosophy of Software Design
John Ousterhout · Yaknyam Press, 2018
Book
04
Reflections on Trusting Trust
Ken Thompson · ACM Turing Award Lecture, 1984
Paper
05
The Rust Programming Language (The Book)
Steve Klabnik & Carol Nichols · rust-lang.org
Docs
06
You Don't Know JS (series)
Kyle Simpson · GitHub / O'Reilly
Blog
07
Clean Architecture
Robert C. Martin · Prentice Hall, 2017
Book
08
MapReduce: Simplified Data Processing on Large Clusters
Dean & Ghemawat · OSDI, 2004
Paper

Share the Knowledge.

Join the conversation.

Leave a Comment

JT
James Tao
Feb 28, 2026 · 14:22

The section on attention mechanisms finally made it click for me. I've read three textbooks and this article explained it better in 1,200 words. The analogy with spotlight allocation was particularly elegant.

SP
Sofia Park
Feb 15, 2026 · 09:47

As someone coming from a Python background, the Rust article felt like being told you've been riding with training wheels your whole life. Simultaneously humbling and invigorating. The borrow checker section was a revelation.

MV
Marco Villanueva
Jan 31, 2026 · 17:05

The HTMX piece aged incredibly well. My team just ripped out a 40k-line React codebase and replaced it with server-side templates + HTMX. Build times went from 4 minutes to 8 seconds. Valleys & Bytes called it months ago.

Read deeper.
Think further.

Choose a plan that fits how deep you want to go. From free weekly digests to full archive access and community perks.

no spam · unsubscribe anytime · your data stays yours

Hiker
0 / month
  • Weekly newsletter
  • 3 free articles / month
  • Community comments
  • Public code snippets
Summit
499 / month
  • Everything in Explorer
  • Live Q&A sessions
  • Private Discord community
  • Source code repositories
  • 1-on-1 monthly office hour

Or just subscribe free — no plan required:

✓ You're subscribed! Welcome to Valleys & Bytes. Check your inbox for a confirmation.