diff --git a/.ipynb_checkpoints/lab-python-error-handling-checkpoint.ipynb b/.ipynb_checkpoints/lab-python-error-handling-checkpoint.ipynb new file mode 100644 index 0000000..f4c6ef6 --- /dev/null +++ b/.ipynb_checkpoints/lab-python-error-handling-checkpoint.ipynb @@ -0,0 +1,98 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "25d7736c-ba17-4aff-b6bb-66eba20fbf4e", + "metadata": {}, + "source": [ + "# Lab | Error Handling" + ] + }, + { + "cell_type": "markdown", + "id": "bc99b386-7508-47a0-bcdb-d969deaf6c8b", + "metadata": {}, + "source": [ + "## Exercise: Error Handling for Managing Customer Orders\n", + "\n", + "The implementation of your code for managing customer orders assumes that the user will always enter a valid input. \n", + "\n", + "For example, we could modify the `initialize_inventory` function to include error handling.\n", + " - If the user enters an invalid quantity (e.g., a negative value or a non-numeric value), display an error message and ask them to re-enter the quantity for that product.\n", + " - Use a try-except block to handle the error and continue prompting the user until a valid quantity is entered.\n", + "\n", + "```python\n", + "# Step 1: Define the function for initializing the inventory with error handling\n", + "def initialize_inventory(products):\n", + " inventory = {}\n", + " for product in products:\n", + " valid_quantity = False\n", + " while not valid_quantity:\n", + " try:\n", + " quantity = int(input(f\"Enter the quantity of {product}s available: \"))\n", + " if quantity < 0:\n", + " raise ValueError(\"Invalid quantity! Please enter a non-negative value.\")\n", + " valid_quantity = True\n", + " except ValueError as error:\n", + " print(f\"Error: {error}\")\n", + " inventory[product] = quantity\n", + " return inventory\n", + "\n", + "# Or, in another way:\n", + "\n", + "def initialize_inventory(products):\n", + " inventory = {}\n", + " for product in products:\n", + " valid_input = False\n", + " while not valid_input:\n", + " try:\n", + " quantity = int(input(f\"Enter the quantity of {product}s available: \"))\n", + " if quantity >= 0:\n", + " inventory[product] = quantity\n", + " valid_input = True\n", + " else:\n", + " print(\"Quantity cannot be negative. Please enter a valid quantity.\")\n", + " except ValueError:\n", + " print(\"Invalid input. Please enter a valid quantity.\")\n", + " return inventory\n", + "```\n", + "\n", + "Let's enhance your code by implementing error handling to handle invalid inputs.\n", + "\n", + "Follow the steps below to complete the exercise:\n", + "\n", + "2. Modify the `calculate_total_price` function to include error handling.\n", + " - If the user enters an invalid price (e.g., a negative value or a non-numeric value), display an error message and ask them to re-enter the price for that product.\n", + " - Use a try-except block to handle the error and continue prompting the user until a valid price is entered.\n", + "\n", + "3. Modify the `get_customer_orders` function to include error handling.\n", + " - If the user enters an invalid number of orders (e.g., a negative value or a non-numeric value), display an error message and ask them to re-enter the number of orders.\n", + " - If the user enters an invalid product name (e.g., a product name that is not in the inventory), or that doesn't have stock available, display an error message and ask them to re-enter the product name. *Hint: you will need to pass inventory as a parameter*\n", + " - Use a try-except block to handle the error and continue prompting the user until a valid product name is entered.\n", + "\n", + "4. Test your code by running the program and deliberately entering invalid quantities and product names. Make sure the error handling mechanism works as expected.\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/.ipynb_checkpoints/lab-python-list-comprehension-checkpoint.ipynb b/.ipynb_checkpoints/lab-python-list-comprehension-checkpoint.ipynb new file mode 100644 index 0000000..39856c6 --- /dev/null +++ b/.ipynb_checkpoints/lab-python-list-comprehension-checkpoint.ipynb @@ -0,0 +1,358 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "25d7736c-ba17-4aff-b6bb-66eba20fbf4e", + "metadata": {}, + "source": [ + "# Lab | List, Dict and Set Comprehension" + ] + }, + { + "cell_type": "markdown", + "id": "7dd3cbde-675a-4b81-92c3-f728846dbe06", + "metadata": {}, + "source": [ + "## Exercise: Managing Customer Orders Optimized with Comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7db6a154-4bbb-439c-9404-5820a799c0af", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "5d500160-2fb7-4777-b5e4-09d45ebaf328", + "metadata": {}, + "source": [ + "In the previous exercise, you developed a program to manage customer orders and inventory. Now, let's take it a step further and incorporate comprehension into your code.\n", + "\n", + "Follow the steps below to complete the exercise:\n", + "\n", + "1. Review your code from the previous exercise and identify areas where you can apply comprehension to simplify and streamline your code. \n", + "\n", + " - *Hint: Apply it to initialize inventory, updating the inventory and printing the updated inventory.*\n", + " \n", + " - For example, in initializing the inventory, we could have:\n", + " \n", + " ```python\n", + " def initialize_inventory(products):\n", + " inventory = {product: int(input(f\"Enter the quantity of {product}s available: \")) for product in products}\n", + " return inventory\n", + "\n", + " ```\n", + "
\n", + " \n", + " \n", + "2. Modify the function get_customer_orders so it prompts the user to enter the number of customer orders and gathers the product names using a loop and user input. Use comprehension.\n", + "\n", + "3. Add a new function to calculate the total price of the customer order. For each product in customer_orders, prompt the user to enter the price of that product. Use comprehension to calculate the total price. Note: assume that the user can only have 1 unit of each product.\n", + "\n", + "4. Modify the update_inventory function to remove the product from the inventory if its quantity becomes zero after fulfilling the customer orders. Use comprehension to filter out the products with a quantity of zero from the inventory.\n", + "\n", + "5. Print the total price of the customer order.\n", + "\n", + "Your code should produce output similar to the following:\n", + "\n", + "```python\n", + "Enter the quantity of t-shirts available: 5\n", + "Enter the quantity of mugs available: 4\n", + "Enter the quantity of hats available: 3\n", + "Enter the quantity of books available: 2\n", + "Enter the quantity of keychains available: 1\n", + "Enter the number of customer orders: 2\n", + "Enter the name of a product that a customer wants to order: hat\n", + "Enter the name of a product that a customer wants to order: keychain\n", + "\n", + "Order Statistics:\n", + "Total Products Ordered: 2\n", + "Percentage of Unique Products Ordered: 40.0\n", + "\n", + "Updated Inventory:\n", + "t-shirt: 5\n", + "mug: 4\n", + "hat: 2\n", + "book: 2\n", + "Enter the price of keychain: 5\n", + "Enter the price of hat: 10\n", + "Total Price: 15.0\n", + "\n", + "```\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "9a63bcdf-0ac3-4e5b-912b-ffab6f423f03", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "--- Inventory Initialization ---\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Enter the quantity of 'Laptop' available: 6\n", + "Enter the quantity of 'Mouse' available: 5\n", + "Enter the quantity of 'Keyboard' available: 6\n", + "Enter the quantity of 'Monitor' available: 7\n", + "Enter the quantity of 'Webcam' available: 8\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "--- Customer Order Entry ---\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Enter the number of unique products to order: 4\n", + "Enter the name of product #1 to order: Laptop\n", + "Enter the name of product #2 to order: Webcam\n", + "Enter the name of product #3 to order: Monitor\n", + "Enter the name of product #4 to order: Keyboard\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "--- Order Statistics ---\n", + "Total Products Ordered: 4\n", + "Percentage of Unique Products Ordered: 80.0%\n", + "\n", + "--- Updating Inventory ---\n", + "Inventory reduced for 'Monitor'. New quantity: 6\n", + "Inventory reduced for 'Webcam'. New quantity: 7\n", + "Inventory reduced for 'Keyboard'. New quantity: 5\n", + "Inventory reduced for 'Laptop'. New quantity: 5\n", + "\n", + "--- Final Updated Inventory ---\n", + "**Laptop**: 5\n", + "**Mouse**: 5\n", + "**Keyboard**: 5\n", + "**Monitor**: 6\n", + "**Webcam**: 7\n", + "\n", + "--- Calculating Total Price ---\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Enter the price of 'Monitor': 150\n", + "Enter the price of 'Webcam': 50\n", + "Enter the price of 'Keyboard': 40\n", + "Enter the price of 'Laptop': 600\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Total Price: **840.00**\n" + ] + } + ], + "source": [ + "import math\n", + "\n", + "# Initial list of available product names\n", + "AVAILABLE_PRODUCTS = [\"Laptop\", \"Mouse\", \"Keyboard\", \"Monitor\", \"Webcam\"]\n", + "\n", + "## 1. Inventory Management Functions with Comprehension\n", + "\n", + "def initialize_inventory(products):\n", + " \"\"\"\n", + " Initializes the inventory using a DICTIONARY COMPREHENSION \n", + " and user input for initial quantities.\n", + " \"\"\"\n", + " print(\"\\n--- Inventory Initialization ---\")\n", + " \n", + " # Dictionary Comprehension for initialization\n", + " inventory = {\n", + " product: int(input(f\"Enter the quantity of '{product}' available: \")) \n", + " for product in products\n", + " }\n", + " return inventory\n", + "\n", + "def update_inventory(customer_orders, inventory):\n", + " \"\"\"\n", + " Updates the inventory based on customer orders and uses a DICTIONARY \n", + " COMPREHENSION to filter out products with zero quantity.\n", + " \"\"\"\n", + " print(\"\\n--- Updating Inventory ---\")\n", + " \n", + " # 1. Decrement quantities for ordered products\n", + " for product in customer_orders:\n", + " if product in inventory and inventory[product] > 0:\n", + " inventory[product] -= 1\n", + " print(f\"Inventory reduced for '{product}'. New quantity: {inventory[product]}\")\n", + " elif product in inventory and inventory[product] == 0:\n", + " print(f\"Warning: '{product}' was ordered but is out of stock.\")\n", + " \n", + " # 2. Dictionary Comprehension to filter out zero-quantity items\n", + " # This creates a NEW dictionary, effectively removing items with quantity <= 0\n", + " updated_inventory = {\n", + " product: quantity\n", + " for product, quantity in inventory.items() \n", + " if quantity > 0\n", + " }\n", + " \n", + " return updated_inventory\n", + "\n", + "def print_updated_inventory(inventory):\n", + " \"\"\"\n", + " Prints the final state of the inventory dictionary, only showing items \n", + " with positive stock. Uses a concise loop for clean output.\n", + " \"\"\"\n", + " print(\"\\n--- Final Updated Inventory ---\")\n", + " for product, quantity in inventory.items():\n", + " print(f\"**{product}**: {quantity}\")\n", + "\n", + "## 2. Order Management Functions\n", + "\n", + "def get_customer_orders():\n", + " \"\"\"\n", + " Prompts the user for the number of orders and gathers product names \n", + " using a list/set comprehension-style approach with user input.\n", + " \n", + " Note: Since the input function must be called inside the loop's \n", + " context, we use a standard loop to collect names, and then convert \n", + " to a set for uniqueness.\n", + " \"\"\"\n", + " print(\"\\n--- Customer Order Entry ---\")\n", + " \n", + " while True:\n", + " try:\n", + " num_orders = int(input(\"Enter the number of unique products to order: \"))\n", + " if num_orders >= 0:\n", + " break\n", + " else:\n", + " print(\"Please enter a non-negative number.\")\n", + " except ValueError:\n", + " print(\"Invalid input. Please enter a whole number.\")\n", + "\n", + " # Standard loop to collect input, then a SET to ensure unique products\n", + " ordered_products = set()\n", + " for i in range(num_orders):\n", + " product_name = input(f\"Enter the name of product #{i+1} to order: \").strip()\n", + " ordered_products.add(product_name)\n", + " \n", + " # Note: If we were gathering *quantities* with a comprehension, \n", + " # the syntax would be cleaner, but here, the input() call must be inside \n", + " # the loop, which makes a standard approach clearer for sequential inputs.\n", + " \n", + " # Return the set of unique orders\n", + " return ordered_products\n", + "\n", + "def calculate_order_total_price(customer_orders):\n", + " \"\"\"\n", + " Prompts the user for the price of each ordered product and calculates \n", + " the total using a GENERATOR EXPRESSION inside the sum() function.\n", + " \n", + " :param customer_orders: The set of unique products ordered.\n", + " :return: The total cost of the order (float).\n", + " \"\"\"\n", + " print(\"\\n--- Calculating Total Price ---\")\n", + " \n", + " # Generator Expression for calculating the sum of prices\n", + " total_price = sum(\n", + " float(input(f\"Enter the price of '{product}': \"))\n", + " for product in customer_orders\n", + " )\n", + " \n", + " return total_price\n", + "\n", + "## 3. Statistics Functions (From previous exercise, kept for completeness)\n", + "\n", + "def calculate_order_statistics(customer_orders, products):\n", + " \"\"\"Calculates order statistics.\"\"\"\n", + " total_products_ordered = len(customer_orders)\n", + " total_available_products = len(products)\n", + " \n", + " if total_available_products > 0:\n", + " percentage_ordered = (total_products_ordered / total_available_products) * 100\n", + " else:\n", + " percentage_ordered = 0.0\n", + " \n", + " return total_products_ordered, percentage_ordered\n", + "\n", + "def print_order_statistics(order_statistics):\n", + " \"\"\"Prints the calculated order statistics.\"\"\"\n", + " total_ordered, percentage = order_statistics\n", + " \n", + " print(\"\\n--- Order Statistics ---\")\n", + " print(f\"Total Products Ordered: {total_ordered}\")\n", + " print(f\"Percentage of Unique Products Ordered: {percentage:.1f}%\")\n", + "\n", + "## --- Main Program Execution ---\n", + "\n", + "# 1. Initialize Inventory (uses comprehension)\n", + "inventory_data = initialize_inventory(AVAILABLE_PRODUCTS)\n", + "\n", + "# 2. Get Customer Orders (uses loop/set for unique product names)\n", + "orders_set = get_customer_orders()\n", + "\n", + "# 3. Calculate Statistics\n", + "stats = calculate_order_statistics(orders_set, AVAILABLE_PRODUCTS)\n", + "print_order_statistics(stats)\n", + "\n", + "# 4. Update Inventory (uses comprehension to filter out zero stock)\n", + "final_inventory = update_inventory(orders_set, inventory_data)\n", + "print_updated_inventory(final_inventory)\n", + "\n", + "# 5. Calculate and Print Total Price (uses generator expression)\n", + "total_cost = calculate_order_total_price(orders_set)\n", + "print(f\"\\nTotal Price: **{total_cost:.2f}**\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "800ef206-78ed-4fed-8cae-71648dd61906", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [conda env:base] *", + "language": "python", + "name": "conda-base-py" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/anaconda_projects/db/project_filebrowser.db b/anaconda_projects/db/project_filebrowser.db new file mode 100644 index 0000000..3fa3a4a Binary files /dev/null and b/anaconda_projects/db/project_filebrowser.db differ diff --git a/lab-python-error-handling.ipynb b/lab-python-error-handling.ipynb index f4c6ef6..131fc18 100644 --- a/lab-python-error-handling.ipynb +++ b/lab-python-error-handling.ipynb @@ -72,13 +72,328 @@ "\n", "4. Test your code by running the program and deliberately entering invalid quantities and product names. Make sure the error handling mechanism works as expected.\n" ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "325ef2d0-9765-42f5-ba2b-3d32e3dce5ff", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "--- Inventory Initialization ---\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Enter the quantity of 'Laptop' available: 10\n", + "Enter the quantity of 'Mouse' available: 12\n", + "Enter the quantity of 'Keyboard' available: 14\n", + "Enter the quantity of 'Monitor' available: 16\n", + "Enter the quantity of 'Webcam' available: 18\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "--- Customer Order Entry ---\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Enter the number of unique products to order: 3\n", + "Enter the name of product #1 to order: Laptop\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "'Laptop' added to the order set.\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Enter the name of product #2 to order: Mouse\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "'Mouse' added to the order set.\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Enter the name of product #3 to order: Keyboard\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "'Keyboard' added to the order set.\n", + "\n", + "--- Order Statistics ---\n", + "Total Products Ordered: 3\n", + "Percentage of Unique Products Ordered: 60.0%\n", + "\n", + "--- Updating Inventory ---\n", + "Inventory reduced for 'Mouse'. New quantity: 11\n", + "Inventory reduced for 'Laptop'. New quantity: 9\n", + "Inventory reduced for 'Keyboard'. New quantity: 13\n", + "\n", + "--- Final Updated Inventory ---\n", + "**Laptop**: 9\n", + "**Mouse**: 11\n", + "**Keyboard**: 13\n", + "**Monitor**: 16\n", + "**Webcam**: 18\n", + "\n", + "--- Calculating Total Price ---\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Enter the price of 'Mouse': 40\n", + "Enter the price of 'Laptop': 700\n", + "Enter the price of 'Keyboard': 40\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Total Price: **780.00**\n" + ] + } + ], + "source": [ + "import math\n", + "\n", + "# Initial list of available product names\n", + "AVAILABLE_PRODUCTS = [\"Laptop\", \"Mouse\", \"Keyboard\", \"Monitor\", \"Webcam\"]\n", + "\n", + "## 1. Inventory Management Functions with Error Handling\n", + "\n", + "def initialize_inventory(products):\n", + " \"\"\"\n", + " Initializes the inventory dictionary. Includes error handling to ensure \n", + " the quantity entered is a non-negative integer.\n", + " \"\"\"\n", + " inventory = {}\n", + " print(\"\\n--- Inventory Initialization ---\")\n", + " for product in products:\n", + " valid_input = False\n", + " while not valid_input:\n", + " try:\n", + " # Attempt to convert input to integer\n", + " quantity = int(input(f\"Enter the quantity of '{product}' available: \"))\n", + " \n", + " # Check for non-negative value\n", + " if quantity >= 0:\n", + " inventory[product] = quantity\n", + " valid_input = True # Exit the validation loop\n", + " else:\n", + " # Raise a specific error for negative numbers\n", + " raise ValueError(\"Quantity cannot be negative.\")\n", + " except ValueError as e:\n", + " # Handle conversion errors (non-numeric input) or the raised ValueError\n", + " print(f\"Error: Invalid input. {e}. Please enter a whole number.\")\n", + " return inventory\n", + "\n", + "def update_inventory(customer_orders, inventory):\n", + " \"\"\"\n", + " Updates the inventory based on customer orders and filters out products \n", + " with zero quantity using a dictionary comprehension.\n", + " \n", + " NOTE: This uses a copy of the inventory dictionary to prevent side effects\n", + " during the update process.\n", + " \"\"\"\n", + " print(\"\\n--- Updating Inventory ---\")\n", + " \n", + " # 1. Decrement quantities for ordered products\n", + " for product in customer_orders:\n", + " if product in inventory and inventory[product] > 0:\n", + " inventory[product] -= 1\n", + " print(f\"Inventory reduced for '{product}'. New quantity: {inventory[product]}\")\n", + " elif product in inventory and inventory[product] == 0:\n", + " print(f\"Warning: '{product}' was ordered but is out of stock.\")\n", + " \n", + " # 2. Dictionary Comprehension to filter out zero-quantity items\n", + " updated_inventory = {\n", + " product: quantity\n", + " for product, quantity in inventory.items() \n", + " if quantity > 0\n", + " }\n", + " \n", + " return updated_inventory\n", + "\n", + "def print_updated_inventory(inventory):\n", + " \"\"\"Prints the final state of the inventory dictionary.\"\"\"\n", + " print(\"\\n--- Final Updated Inventory ---\")\n", + " for product, quantity in inventory.items():\n", + " print(f\"**{product}**: {quantity}\")\n", + "\n", + "## 2. Order Management Functions with Error Handling\n", + "\n", + "def get_customer_orders(inventory):\n", + " \"\"\"\n", + " Gathers product names, validating the number of orders and \n", + " product names (checking stock and existence).\n", + " \n", + " :param inventory: The dictionary of current stock levels.\n", + " :return: A set of unique product names ordered by the customer.\n", + " \"\"\"\n", + " customer_orders = set()\n", + " print(\"\\n--- Customer Order Entry ---\")\n", + " \n", + " # 1. Validation for number of orders\n", + " while True:\n", + " try:\n", + " num_orders_input = input(\"Enter the number of unique products to order: \")\n", + " num_orders = int(num_orders_input)\n", + " \n", + " if num_orders >= 0:\n", + " break\n", + " else:\n", + " print(\"Error: Number of orders cannot be negative.\")\n", + " except ValueError:\n", + " print(\"Error: Invalid input. Please enter a whole number for the number of orders.\")\n", + "\n", + " # 2. Loop to collect unique orders with product validation\n", + " i = 0\n", + " while i < num_orders:\n", + " product_name = input(f\"Enter the name of product #{i+1} to order: \").strip()\n", + " \n", + " # Error Check 1: Product must exist in inventory keys\n", + " if product_name not in inventory:\n", + " print(f\"Error: Product '{product_name}' not found in the inventory.\")\n", + " continue \n", + " \n", + " # Error Check 2: Product must have stock available\n", + " if inventory[product_name] <= 0:\n", + " print(f\"Error: '{product_name}' is currently out of stock.\")\n", + " continue\n", + " \n", + " # If valid and in stock, add to the set\n", + " if product_name not in customer_orders:\n", + " customer_orders.add(product_name)\n", + " print(f\"'{product_name}' added to the order set.\")\n", + " else:\n", + " print(f\"Note: '{product_name}' is already in the order. Skipping duplicate.\")\n", + " \n", + " i += 1 # Only increment counter after a valid, unique product is added\n", + " \n", + " return customer_orders\n", + "\n", + "def calculate_order_total_price(customer_orders):\n", + " \"\"\"\n", + " Prompts the user for the price of each ordered product, including error \n", + " handling to ensure the price is a non-negative number.\n", + " \n", + " :param customer_orders: The set of unique products ordered.\n", + " :return: The total cost of the order (float).\n", + " \"\"\"\n", + " print(\"\\n--- Calculating Total Price ---\")\n", + " total_price = 0.0\n", + " \n", + " for product in customer_orders:\n", + " valid_price = False\n", + " while not valid_price:\n", + " try:\n", + " price_input = input(f\"Enter the price of '{product}': \")\n", + " price = float(price_input)\n", + " \n", + " # Check for non-negative value\n", + " if price >= 0:\n", + " total_price += price\n", + " valid_price = True\n", + " else:\n", + " raise ValueError(\"Price cannot be negative.\")\n", + " except ValueError as e:\n", + " # Handle conversion errors or the raised ValueError\n", + " print(f\"Error: Invalid input. {e}. Please enter a positive numeric value for the price.\")\n", + " \n", + " return total_price\n", + "\n", + "## 3. Statistics Functions \n", + "\n", + "def calculate_order_statistics(customer_orders, products):\n", + " \"\"\"Calculates order statistics.\"\"\"\n", + " total_products_ordered = len(customer_orders)\n", + " total_available_products = len(products)\n", + " \n", + " if total_available_products > 0:\n", + " percentage_ordered = (total_products_ordered / total_available_products) * 100\n", + " else:\n", + " percentage_ordered = 0.0\n", + " \n", + " return total_products_ordered, percentage_ordered\n", + "\n", + "def print_order_statistics(order_statistics):\n", + " \"\"\"Prints the calculated order statistics.\"\"\"\n", + " total_ordered, percentage = order_statistics\n", + " \n", + " print(\"\\n--- Order Statistics ---\")\n", + " print(f\"Total Products Ordered: {total_ordered}\")\n", + " print(f\"Percentage of Unique Products Ordered: {percentage:.1f}%\")\n", + "\n", + "## --- Main Program Execution ---\n", + "\n", + "# 1. Initialize Inventory (uses error handling)\n", + "# Example of valid products: Laptop, Mouse, Keyboard, Monitor, Webcam\n", + "inventory_data = initialize_inventory(AVAILABLE_PRODUCTS)\n", + "\n", + "# 2. Get Customer Orders (uses error handling and inventory check)\n", + "orders_set = get_customer_orders(inventory_data)\n", + "\n", + "# 3. Calculate Statistics\n", + "stats = calculate_order_statistics(orders_set, AVAILABLE_PRODUCTS)\n", + "print_order_statistics(stats)\n", + "\n", + "# 4. Update Inventory (uses comprehension to filter out zero stock)\n", + "final_inventory = update_inventory(orders_set, inventory_data)\n", + "# Note: inventory_data is modified in place, but the zero-stock items\n", + "# are filtered into the final_inventory dictionary for printing.\n", + "print_updated_inventory(final_inventory)\n", + "\n", + "# 5. Calculate and Print Total Price (uses error handling)\n", + "total_cost = calculate_order_total_price(orders_set)\n", + "print(f\"\\nTotal Price: **{total_cost:.2f}**\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "07870ae6-2abd-4475-8577-2537bf3dc2c9", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python [conda env:base] *", "language": "python", - "name": "python3" + "name": "conda-base-py" }, "language_info": { "codemirror_mode": { @@ -90,7 +405,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.13.5" } }, "nbformat": 4, diff --git a/lab-python-list-comprehension.ipynb b/lab-python-list-comprehension.ipynb new file mode 100644 index 0000000..39856c6 --- /dev/null +++ b/lab-python-list-comprehension.ipynb @@ -0,0 +1,358 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "25d7736c-ba17-4aff-b6bb-66eba20fbf4e", + "metadata": {}, + "source": [ + "# Lab | List, Dict and Set Comprehension" + ] + }, + { + "cell_type": "markdown", + "id": "7dd3cbde-675a-4b81-92c3-f728846dbe06", + "metadata": {}, + "source": [ + "## Exercise: Managing Customer Orders Optimized with Comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7db6a154-4bbb-439c-9404-5820a799c0af", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "5d500160-2fb7-4777-b5e4-09d45ebaf328", + "metadata": {}, + "source": [ + "In the previous exercise, you developed a program to manage customer orders and inventory. Now, let's take it a step further and incorporate comprehension into your code.\n", + "\n", + "Follow the steps below to complete the exercise:\n", + "\n", + "1. Review your code from the previous exercise and identify areas where you can apply comprehension to simplify and streamline your code. \n", + "\n", + " - *Hint: Apply it to initialize inventory, updating the inventory and printing the updated inventory.*\n", + " \n", + " - For example, in initializing the inventory, we could have:\n", + " \n", + " ```python\n", + " def initialize_inventory(products):\n", + " inventory = {product: int(input(f\"Enter the quantity of {product}s available: \")) for product in products}\n", + " return inventory\n", + "\n", + " ```\n", + "
\n", + " \n", + " \n", + "2. Modify the function get_customer_orders so it prompts the user to enter the number of customer orders and gathers the product names using a loop and user input. Use comprehension.\n", + "\n", + "3. Add a new function to calculate the total price of the customer order. For each product in customer_orders, prompt the user to enter the price of that product. Use comprehension to calculate the total price. Note: assume that the user can only have 1 unit of each product.\n", + "\n", + "4. Modify the update_inventory function to remove the product from the inventory if its quantity becomes zero after fulfilling the customer orders. Use comprehension to filter out the products with a quantity of zero from the inventory.\n", + "\n", + "5. Print the total price of the customer order.\n", + "\n", + "Your code should produce output similar to the following:\n", + "\n", + "```python\n", + "Enter the quantity of t-shirts available: 5\n", + "Enter the quantity of mugs available: 4\n", + "Enter the quantity of hats available: 3\n", + "Enter the quantity of books available: 2\n", + "Enter the quantity of keychains available: 1\n", + "Enter the number of customer orders: 2\n", + "Enter the name of a product that a customer wants to order: hat\n", + "Enter the name of a product that a customer wants to order: keychain\n", + "\n", + "Order Statistics:\n", + "Total Products Ordered: 2\n", + "Percentage of Unique Products Ordered: 40.0\n", + "\n", + "Updated Inventory:\n", + "t-shirt: 5\n", + "mug: 4\n", + "hat: 2\n", + "book: 2\n", + "Enter the price of keychain: 5\n", + "Enter the price of hat: 10\n", + "Total Price: 15.0\n", + "\n", + "```\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "9a63bcdf-0ac3-4e5b-912b-ffab6f423f03", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "--- Inventory Initialization ---\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Enter the quantity of 'Laptop' available: 6\n", + "Enter the quantity of 'Mouse' available: 5\n", + "Enter the quantity of 'Keyboard' available: 6\n", + "Enter the quantity of 'Monitor' available: 7\n", + "Enter the quantity of 'Webcam' available: 8\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "--- Customer Order Entry ---\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Enter the number of unique products to order: 4\n", + "Enter the name of product #1 to order: Laptop\n", + "Enter the name of product #2 to order: Webcam\n", + "Enter the name of product #3 to order: Monitor\n", + "Enter the name of product #4 to order: Keyboard\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "--- Order Statistics ---\n", + "Total Products Ordered: 4\n", + "Percentage of Unique Products Ordered: 80.0%\n", + "\n", + "--- Updating Inventory ---\n", + "Inventory reduced for 'Monitor'. New quantity: 6\n", + "Inventory reduced for 'Webcam'. New quantity: 7\n", + "Inventory reduced for 'Keyboard'. New quantity: 5\n", + "Inventory reduced for 'Laptop'. New quantity: 5\n", + "\n", + "--- Final Updated Inventory ---\n", + "**Laptop**: 5\n", + "**Mouse**: 5\n", + "**Keyboard**: 5\n", + "**Monitor**: 6\n", + "**Webcam**: 7\n", + "\n", + "--- Calculating Total Price ---\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Enter the price of 'Monitor': 150\n", + "Enter the price of 'Webcam': 50\n", + "Enter the price of 'Keyboard': 40\n", + "Enter the price of 'Laptop': 600\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Total Price: **840.00**\n" + ] + } + ], + "source": [ + "import math\n", + "\n", + "# Initial list of available product names\n", + "AVAILABLE_PRODUCTS = [\"Laptop\", \"Mouse\", \"Keyboard\", \"Monitor\", \"Webcam\"]\n", + "\n", + "## 1. Inventory Management Functions with Comprehension\n", + "\n", + "def initialize_inventory(products):\n", + " \"\"\"\n", + " Initializes the inventory using a DICTIONARY COMPREHENSION \n", + " and user input for initial quantities.\n", + " \"\"\"\n", + " print(\"\\n--- Inventory Initialization ---\")\n", + " \n", + " # Dictionary Comprehension for initialization\n", + " inventory = {\n", + " product: int(input(f\"Enter the quantity of '{product}' available: \")) \n", + " for product in products\n", + " }\n", + " return inventory\n", + "\n", + "def update_inventory(customer_orders, inventory):\n", + " \"\"\"\n", + " Updates the inventory based on customer orders and uses a DICTIONARY \n", + " COMPREHENSION to filter out products with zero quantity.\n", + " \"\"\"\n", + " print(\"\\n--- Updating Inventory ---\")\n", + " \n", + " # 1. Decrement quantities for ordered products\n", + " for product in customer_orders:\n", + " if product in inventory and inventory[product] > 0:\n", + " inventory[product] -= 1\n", + " print(f\"Inventory reduced for '{product}'. New quantity: {inventory[product]}\")\n", + " elif product in inventory and inventory[product] == 0:\n", + " print(f\"Warning: '{product}' was ordered but is out of stock.\")\n", + " \n", + " # 2. Dictionary Comprehension to filter out zero-quantity items\n", + " # This creates a NEW dictionary, effectively removing items with quantity <= 0\n", + " updated_inventory = {\n", + " product: quantity\n", + " for product, quantity in inventory.items() \n", + " if quantity > 0\n", + " }\n", + " \n", + " return updated_inventory\n", + "\n", + "def print_updated_inventory(inventory):\n", + " \"\"\"\n", + " Prints the final state of the inventory dictionary, only showing items \n", + " with positive stock. Uses a concise loop for clean output.\n", + " \"\"\"\n", + " print(\"\\n--- Final Updated Inventory ---\")\n", + " for product, quantity in inventory.items():\n", + " print(f\"**{product}**: {quantity}\")\n", + "\n", + "## 2. Order Management Functions\n", + "\n", + "def get_customer_orders():\n", + " \"\"\"\n", + " Prompts the user for the number of orders and gathers product names \n", + " using a list/set comprehension-style approach with user input.\n", + " \n", + " Note: Since the input function must be called inside the loop's \n", + " context, we use a standard loop to collect names, and then convert \n", + " to a set for uniqueness.\n", + " \"\"\"\n", + " print(\"\\n--- Customer Order Entry ---\")\n", + " \n", + " while True:\n", + " try:\n", + " num_orders = int(input(\"Enter the number of unique products to order: \"))\n", + " if num_orders >= 0:\n", + " break\n", + " else:\n", + " print(\"Please enter a non-negative number.\")\n", + " except ValueError:\n", + " print(\"Invalid input. Please enter a whole number.\")\n", + "\n", + " # Standard loop to collect input, then a SET to ensure unique products\n", + " ordered_products = set()\n", + " for i in range(num_orders):\n", + " product_name = input(f\"Enter the name of product #{i+1} to order: \").strip()\n", + " ordered_products.add(product_name)\n", + " \n", + " # Note: If we were gathering *quantities* with a comprehension, \n", + " # the syntax would be cleaner, but here, the input() call must be inside \n", + " # the loop, which makes a standard approach clearer for sequential inputs.\n", + " \n", + " # Return the set of unique orders\n", + " return ordered_products\n", + "\n", + "def calculate_order_total_price(customer_orders):\n", + " \"\"\"\n", + " Prompts the user for the price of each ordered product and calculates \n", + " the total using a GENERATOR EXPRESSION inside the sum() function.\n", + " \n", + " :param customer_orders: The set of unique products ordered.\n", + " :return: The total cost of the order (float).\n", + " \"\"\"\n", + " print(\"\\n--- Calculating Total Price ---\")\n", + " \n", + " # Generator Expression for calculating the sum of prices\n", + " total_price = sum(\n", + " float(input(f\"Enter the price of '{product}': \"))\n", + " for product in customer_orders\n", + " )\n", + " \n", + " return total_price\n", + "\n", + "## 3. Statistics Functions (From previous exercise, kept for completeness)\n", + "\n", + "def calculate_order_statistics(customer_orders, products):\n", + " \"\"\"Calculates order statistics.\"\"\"\n", + " total_products_ordered = len(customer_orders)\n", + " total_available_products = len(products)\n", + " \n", + " if total_available_products > 0:\n", + " percentage_ordered = (total_products_ordered / total_available_products) * 100\n", + " else:\n", + " percentage_ordered = 0.0\n", + " \n", + " return total_products_ordered, percentage_ordered\n", + "\n", + "def print_order_statistics(order_statistics):\n", + " \"\"\"Prints the calculated order statistics.\"\"\"\n", + " total_ordered, percentage = order_statistics\n", + " \n", + " print(\"\\n--- Order Statistics ---\")\n", + " print(f\"Total Products Ordered: {total_ordered}\")\n", + " print(f\"Percentage of Unique Products Ordered: {percentage:.1f}%\")\n", + "\n", + "## --- Main Program Execution ---\n", + "\n", + "# 1. Initialize Inventory (uses comprehension)\n", + "inventory_data = initialize_inventory(AVAILABLE_PRODUCTS)\n", + "\n", + "# 2. Get Customer Orders (uses loop/set for unique product names)\n", + "orders_set = get_customer_orders()\n", + "\n", + "# 3. Calculate Statistics\n", + "stats = calculate_order_statistics(orders_set, AVAILABLE_PRODUCTS)\n", + "print_order_statistics(stats)\n", + "\n", + "# 4. Update Inventory (uses comprehension to filter out zero stock)\n", + "final_inventory = update_inventory(orders_set, inventory_data)\n", + "print_updated_inventory(final_inventory)\n", + "\n", + "# 5. Calculate and Print Total Price (uses generator expression)\n", + "total_cost = calculate_order_total_price(orders_set)\n", + "print(f\"\\nTotal Price: **{total_cost:.2f}**\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "800ef206-78ed-4fed-8cae-71648dd61906", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [conda env:base] *", + "language": "python", + "name": "conda-base-py" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}