diff --git a/.git-bestPractices b/.git-bestPractices new file mode 100644 index 0000000..95bafbc --- /dev/null +++ b/.git-bestPractices @@ -0,0 +1,5 @@ +#after every update and before any commit/push, run: +- git fetch upstream +- git rebase upstream/main +- git push origin master + diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..0bbab56 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "bowlerr.offline-markdown-preview" + ] +} \ No newline at end of file diff --git a/ROADMAP.md b/ROADMAP.md index 9f01df4..7d681ff 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -9,24 +9,58 @@ This may be subject to change. ## Roadmap 1. Introduction * [x] How course works? - * [x] Motivation and Mindset - * [ ] Asking for help - * [ ] Join the Community - * [x] Computers and Programming Languages (CS Basics) -2. Prerequisites - * [x] Installation of required software - * [x] Text Editor basics - * [x] Command Line basics - * [x] Python - What is it? REPL vs Scripts + * [ ] Motivation and Mindset + * [ ] Asking for Help (WIP) + * [x] Join the Community + * [x] Computer Science basics, Programming and Python +2. Prerequisites + * [x] Software Installation + * [x] Text and Code Editors + * [x] Command Line Basics + * [x] Python - REPL vs Scripts 3. Git Basics * [x] Introduction to Git * [x] Setting up Git and Github - * [x] Git basics -4. Python Foundations - * [x] Output (print), Variables, Core Datatypes - * [x] Math, String operations, Comparisons - * [x] User input, Conditionals + * [x] Git Basics +4. Foundations + * [x] Output, Variables, Core Datatypes + * [x] Arithmetic and String Operations, Comparisons + * [x] User Input and Conditionals * [x] Loops +5. Data Structures + * [ ] Lists (WIP) + * [ ] Tuples (WIP) + * [ ] Sets (WIP) + * [ ] Dictionaries (WIP) + * [ ] Coprehensions (`list`, `dict` `set`) (WIP) +6. Code Organization + * [ ] Functions + * [ ] Scope and Namespaces (LEGB rule) + * [ ] Type Hints + * [ ] Modules +7. Capstone Project 1 + * [ ] Problem Solving + * [ ] Problem Solving - Fizz-Buzz Example + * [ ] Capstone Project - **Hangman game** +8. Errors, Debugging, I/O + * [ ] Understanding Errors and Error Handling + * [ ] `logging` module + * [ ] Debugging tehniques + * [ ] File Handling +9. Capstone Project 2 + * [ ] Git Workflow: Branches and Pull Requests + * [ ] Revisiting Project 1 (hangman game): + * Creating branch, adding features, merging back to `main` + * Loading *words* from external file + * Catching and logging errors + * [ ] Capstone Project +10. Intermediate Python + * [ ] Decorators + * [ ] Generators + * [ ] Context Managers +11. Capstone Project 3 + * [ ] Capstone Project +12. Built-in and Modules * [-] Data Structures * [-] List * [-] Tuple @@ -48,4 +82,87 @@ This may be subject to change. * [ ] Installation of third party libraries * [ ] Working with APIs * [ ] Project 3 - *probably: * weather app -7. Working on Projects, Solving bugs, Reading errors \ No newline at end of file +7. Working on Projects, Solving bugs, Reading errors + * [ ] Motivation and Mindset + * [ ] Asking for Help (WIP) + * [x] Join the Community + * [x] Computer Science basics, Programming and Python +2. Prerequisites + * [x] Software Installation + * [x] Text and Code Editors + * [x] Command Line Basics + * [x] Python - REPL vs Scripts +3. Git Basics + * [x] Introduction to Git + * [x] Setting up Git and Github + * [x] Git Basics +4. Foundations + * [x] Output, Variables, Core Datatypes + * [x] Arithmetic and String Operations, Comparisons + * [x] User Input and Conditionals + * [x] Loops +5. Data Structures + * [x] Lists + * [x] Tuples + * [x] Sets + * [x] Dictionaries +6. Comprehensions + * [ ] List Coprehension + * [ ] Set Coprehension + * [ ] Dict Coprehension +7. Code Organization + * [ ] Functions + * [ ] Scope and Namespaces (LEGB rule) + * [ ] Understanding Errors and Error Handling + * [ ] File Handling + * [ ] Modules +8. Capstone Project 1 + * [ ] Problem Solving + * [ ] Problem Solving - Fizz-Buzz Example + * [ ] Capstone Project +9. Built-in and Modules + * [ ] `math` module + * [ ] `json` module + * [ ] `random` module + * [ ] `datetime` module + * [ ] `pathlib` / `os` module + * [ ] `csv` module + * [ ] `sys` module + * [ ] `re` module +13. Third-party Modules + * [ ] Virtual Environments + * [ ] Using `pip` and `requirements.txt` + * [ ] Creating python package - `pyproject.toml` file + * [ ] ? Linting, Formatting, Type Checking (`ruff`, `mypy`) ? +14. Capstone Project 4 + * [ ] Clean Code Priciples + * [ ] Capstone Project + * [ ] Testing Your Code (`pytest`) + * [ ] Revisit Project 4 + * Develop a testing suite for the project +15. Object Oriented Programming - Part 1 + * [ ] Introduction to classes and instances + * [ ] Methods (instance, class, static) + * [ ] Dunder Methods (`__str__`, `__repr__`, etc...) +16. Capstone Project 5 + * [ ] Capstone Project +17. Object Oriented Programming - Part 2 + * [ ] Four Pillars of Object-Oriented Programming (Encapsulation, Abstraction, Inheritance, Polymorphism) +18. Capstone Project 6 +10. Third-party Modules + * [ ] Virtual Environments + * [ ] Using `pip` and `requirements.txt` + * [ ] Creating python package - `pyproject.toml` file +11. Capstone Project 2 + * [ ] Clean Code Priciples + * [ ] Capstone Project +12. Object Oriented Programming - Part 1 + * [ ] Introduction to classes and instances + * [ ] Methods (instance, class, static) + * [ ] Dunder Methods (`__str__`, `__repr__`, etc...) +13. Capstone Project 3 + * [ ] Capstone Project +14. Object Oriented Programming - Part 2 + * [ ] Four Pillars of Object-Oriented Programming (Encapsulation, Abstraction, Inheritance, Polymorphism) +15. Capstone Project 4 + * [ ] Capstone Project diff --git a/curriculum/01-introduction/03-asking-for-help.md b/curriculum/01-introduction/03-asking-for-help.md index 51b555c..363c961 100644 --- a/curriculum/01-introduction/03-asking-for-help.md +++ b/curriculum/01-introduction/03-asking-for-help.md @@ -6,5 +6,89 @@ sidebar_position: 3 lesson: true isDraft: true --- -# Asking For Help -## Work in progress \ No newline at end of file + +# Asking For Help ❔ +**INTRODUCTION**: Getting stuck in your coding or even a learning is really part of the journey, and that is the number one why this lesson (ask for help) exists. + +## The Goal 🥅⚽ +In this lesson you will learn how to get help whenever you need it. And by the end of this lesson you should be familiar with getting stuck and how to seek for help. + + +## Lesson outline 📝 +* How to Get Help +* Who to Ask for Help +* Where to Ask for Help + +## How to Get Help ❔ +Steps to follow to get help: +* Before you ask, do some checks +* Use the question space +* format your code properly +* Know what to expect next + +### 1. Before You Ask ⤴➡ +Before you ask anything check if: +- your indentations are correct or valid +- your syntax are correct or valid +- your code is complete as you intended + +**If** any of above is False, Fix them and re-run your code. + +**Else**, if all of above is True and error still persist, proceed to the step 2(the question space) of this topic. + + +### 2. The Question space 📰❔ +Paste your code below: + +′′′python + +import A + +′′′ + +### 3. How to Format Your Code 🔃 +- You are required to format your code (_python code_) using the markdown language in order to get the appropriate responses to your help requests. +... + +### 4. What to Expect Next ➡ +Once you have submitted your help request, sit down tight and the appropriate help will be sent straight to you. + +If unfortunately the help response delays or never comes, use the next approach which is _WHO TO ASK_. + + +## Who to Ask for Help 🧔🏻❔ +subs: +* Ask yourself +* Ask someone with experience +* Ask a trusted community +* Ask an Ai agent + +### 1. Ask Yourself Before Anyone +You may say, why myself, i don't know?—Ofcourse you know all the answers to your own questions most of the times. **Ask yourself why, why did the error come; Ask yourself how, how did the error come; and Ask yourself what, what brought up a particular error** :(. You are not actually finding the correct solution to the cause of the error with these questions overnight (as if it was a magic :)), *but* what you are doing is you are training your thinking which may help you think creatively gradually—to solve future problems. "Problem solving requires a creative and effective thinking"—Baldwin.J,. college success(2021). + +After you have had your answers to those three question, store them safely as we will learn how they might become useful later in this lesson. + +### 2. Ask Someone with Experience +Why ask someone with experience?—An experienced programmer, specifically python programmer, knows how to solve or debug almost every bug or error respectively. Therefore asking an experienced person means there is a higher probability you will get a solution to an/a error/bug. + +Now let see how your answers at the _ask yourself_ sub gets useful here. Compare your answers obtained at the _ask yourself_ sub to the ones you obtained from the experienced programmer and **Ask youself one more time—what did i missed?**—Keep this particular answer to yourself (treat it as important), it might help you in your future decisions when debugging other or similar errors later on. + +### 3. Ask a Trusted Community +Though there isn't a full guarantee that a community will contain only experienced programmers,—That is there would be beginners, intermediates and experts—but there are people with at least an experience if not much, these people might have already at least solved a bug which you just met, and could share with you how they handled it—which might be a fantastic approach you could learn also. + +Therefore asking verified communities like the stackoverflow, github, telegram groups, reddit, discord and others i could'nt mention—though one should proceed this with caution—is a must once you are learning the python or any other programming langauge. + +### 4. Ask an AI Agent +AI tools or agents are a smart way to debug errors faster, but the question is—Does the AI agent know the best approch to avoid future code breaks? + +This does not neccessarily mean using AI assistance for debugging errors is bad. But for best decision sake; That is if you know enough or understand how to select the best approach out of the many provided by the AI model, then you are encouraged to proceed with this approach—the advice is simple, that is use AI to recall the best solutions you already know quickly and not to decide the best solutions for you. + +This really counts in a serious project or even in the real world practices, but it is also a good thing to keep it in practice now—even if you are learning. + + +## Where to Ask for Help +- _work in progress_ + + + +[ **_WORK IN PROGRESS_** ] diff --git a/curriculum/04-python-foundations/01-output-variable-datatypes.md b/curriculum/04-python-foundations/01-output-variable-datatypes.md index 24ce11b..ffececc 100644 --- a/curriculum/04-python-foundations/01-output-variable-datatypes.md +++ b/curriculum/04-python-foundations/01-output-variable-datatypes.md @@ -179,7 +179,7 @@ You will need to do this assignment on your own machine. Item price: $67.2 Item available: True ``` -7. Make sure your program works as expected then create a repository and push your code to github +7. Make sure your program works as expected then create a repository and push your code to Github. ## Deepen Your Knowlege Go through these articles to deepen your knowlege about the topics covered in this lesson. diff --git a/curriculum/04-python-foundations/02-math-stringops-comparisons.md b/curriculum/04-python-foundations/02-math-stringops-comparisons.md index d027288..4a8e0bb 100644 --- a/curriculum/04-python-foundations/02-math-stringops-comparisons.md +++ b/curriculum/04-python-foundations/02-math-stringops-comparisons.md @@ -232,7 +232,7 @@ In the last assignment we have declared our shop variables and printed the inven -------------------------------- Thank you for your purchase ! ``` -7. Commit your changes with `git` and push to Github +7. Commit your changes with `git` and push to Github. ## Deepen Your Knowledge 1. Learn more about [Basic math in Python](https://cs.stanford.edu/people/nick/py/python-math.html#math) from article in **Stanford University**, covering all the topics in this lesson but in a different style and a bit more. diff --git a/curriculum/04-python-foundations/04-loops.md b/curriculum/04-python-foundations/04-loops.md index 5621b3f..fbf1519 100644 --- a/curriculum/04-python-foundations/04-loops.md +++ b/curriculum/04-python-foundations/04-loops.md @@ -120,10 +120,12 @@ These statements `break` and `continue` work only in loops. If you try to use th ## Assigment 1. Open `main.py` in your `simple-python-shop` project. -2. Create a new variable named `item_count` and set it to `0` as its initial value. +2. Set `item_quantity` to `0` as its initial value and remove `item_price` variable. 3. Use a `while` loop to repeatedly prompt the user for an item price. - * If the price entered is 0 break out of the loop - * Otherwise, add the price user entered to `total` and increment `item_count` by 1. + * If the price entered is less then 0, print message saying `Invalid price, must be positive`, and skipping the rest of the iteration code, asking user again to enter the price. + * Otherwise check if the price entered is 0 and if so, break out of the loop. + * Otherwise, check if `item_stock - item_quantity` is more than `1` and if not, break out of the loop, informing the user we are out of stock. + * Otherwise, add the price user entered to `total` and increment `item_quantity` by 1. 4. When the loop finishes, determine if the `total` can have a discount and print out the final receipt. 5. Make sure your program works, then commit and push your code diff --git a/curriculum/05-data-structures/01-list.md b/curriculum/05-data-structures/01-list.md index 805873f..4adb8f6 100644 --- a/curriculum/05-data-structures/01-list.md +++ b/curriculum/05-data-structures/01-list.md @@ -7,7 +7,6 @@ lesson: true isDraft: true --- # List -## Introduction {#introduction} Up until now we have stored a single value in a variable, but what if we need to hold multiple values in some variable? Do we create multiple variables? Of course not, Python has a *built-in* mechanisms for dealing with collections of data which we call **data structures**. In this lesson we first take a look at **list**. Lists in Python are *built-in* data structure for storing ordered collections of items. They are **ordered** meaning they keep the order in which data came in. They are also **mutable** which means we can change them in place without creating a new copy. They can hold any other type of data including other lists or other data structures. Lists are probably the most used data structure in Python. @@ -147,19 +146,37 @@ for item in a: This is very useful as we often need to work with specific elements from the list. :::explore[Learn more about Python lists] - Learn more about Python Lists from these resources: -* [Google for Education - Python Lists](https://developers.google.com/edu/python/lists) -* [Official Python Documentation on Lists](https://docs.python.org/3/library/stdtypes.html#typesseq-list) -* [Official Python Documentation on Data Structures - more on Lists](https://docs.python.org/3/tutorial/datastructures.html#more-on-lists) - +* Learn about `zip()` function from [zip() function - RealPython](https://realpython.com/ref/builtin-functions/zip/) and [zip() function - official Python Documentation](https://docs.python.org/3.3/library/functions.html#zip) that allows for combining of multiple lists (or other iterables as we will see later) by producing **tuples** (we cover these in the next lesson) +* Learn about `.sort()` method from [official Python Documentation](https://docs.python.org/3/library/stdtypes.html#list.sort) which is very useful in sorting lists in-place. Sorting iterables is a very useful tehnique and there are multiple arguments and ways to sort iterables in Python. Be sure to read this [Sorting Tehniques - official Python documentation](https://docs.python.org/3/howto/sorting.html) to familiarize yourself with tehniques used. +* Go thrue all the available methods on the lists in [More on Lists - official Python documentation](https://docs.python.org/3/tutorial/datastructures.html#more-on-lists), as these will come in handy when working on your projects. You do not need to remember them all, but just read thrue them and their intended purpouse so you will know what is out there. ::: ## Exercise -Complete [Exercise 05 — The Cozy Bakery Inventory](#) to practice list creation, indexing, modification, and using python documentation to solve list tasks. +Complete [[TODO] Exercise 05 — WorkingTitle](#) to practice list creation, indexing, modification, and using python documentation to solve list tasks. ## Assignment {#assignment} -**Todo** +1. Open `main.py` file in our `simple-python-shop` directory +2. Replace `item_name`, `item_price` and `item_stock` static values with an empty list. +3. In *infinite loop* ask the user to fill up the inventory by typing in a name, price and stock level of item. + * If user types **empty string**, break out of the loop and continue with program execution. + * User should enter all of the information on the same line. Use `.split()` method on the inputed string to catch all information needed. **Do not forget** to cast `price` to `float` and `stock` to `integer`. + * Append every information to their own respective list. +4. Display the inventory by using `zip()` function and combining all three lists to display items one by one. +5. Create variable `order` and assign it an empty list. +6. Create another *infinite loop* and inside the loop ask the user to enter the name of the item he wants to buy. + * If user enters empty string, break out of the loop. + * If the item user entered is in the `item_name` list, find its index position and assign it to variable, otherwise inform the user that there is no such item at the moment, and **continue** with next iteration of loop + * When you have an index of the item user asked, ask the user to enter quantity of the items. Check if entered item quantity is not bigger then actual item stock and if it is, tell the user that we do not have that many items in stock, then **continue** with new iteration. + * If we have the item and have enough of stock, add the total for item (item price multiplied by quantity) to `order` list. + * Decrease the stock number of items by the quantity ammount and if item stock reaches 0, remove the item (and its relevant info) from the inventory lists. +7. Calculate the total by adding all the numbers in `order` list using `sum()` function and calculate whether to give 10% discount (if `total > 100`). +8. Print out the final receipt in the following format: + ``` + Your total is: $ + ``` +9. Print the inventory after shopping. +10. Make sure your application works correctly, commit the changes and push your code to Github. ## What's Next {#next-lesson} Lists are ordered and mutable, which makes them ideal for collections that grow or change over time. But what if you need an ordered collection that **cannot** be modified once created? diff --git a/curriculum/05-data-structures/02-tuple.md b/curriculum/05-data-structures/02-tuple.md index d97d13e..8be316b 100644 --- a/curriculum/05-data-structures/02-tuple.md +++ b/curriculum/05-data-structures/02-tuple.md @@ -7,7 +7,6 @@ lesson: true isDraft: true --- # Tuple -## Introduction {#introduction} Tuple is an ordered and immutable collection data structure. **Ordered** meaning it keeps the order of elements in which they are inserted, and **immutable** means that once the tuple is created it cannot change, and you cannot add or remove elements from it. ## Lesson Overview {#overview} @@ -39,7 +38,7 @@ print(f"First element: {a[0]} - Last element: {a[-1]}") ``` ## Useful methods -Unlike functions, as we cannot modify tuples, we don't have a lot of methods available to us, but we will list a few. +Unlike lists, as we cannot modify tuples, we don't have a lot of methods available to us, but we will list a few. * `count()` - returns the number of times a specified value appears in tuple. ```python interactive numbers = (1, 2, 3, 3, 3, 4, 5) @@ -52,12 +51,24 @@ Unlike functions, as we cannot modify tuples, we don't have a lot of methods ava ``` :::explore[Learn more about Python Tuples] -* [Python built-in types: tuples from RealPython](https://realpython.com/ref/builtin-types/tuple/) -* [Tuples and Sequences from official Python documentation](https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences) +Deep dive into Python tuples in this [Deep Dive: tuples](https://realpython.com/python-tuple/) article by **Real Python** which takes you deep in topic of tuples and their usecases. ::: +## Exercise +Complete [[TODO] Exercise 06 — WorkingTitle](#) to practice tuples. + ## Assignment {#assignment} -**Todo** +Using lists to separatly hold multiple related values is brittle and will break if you do not pay attention to all lists containing data. In this assigment we will deal with those issues by using tuples. + +1. Open our `main.py` file we have been working on +2. Create a new empty list called `inventory`. This will hold tuples of related data `(product_name, product_price, product_stock)`. +3. Delete previusly defined `item_name`, `item_price` and `item_stock` variables, we wont need them anymore. +4. Just like before, in **infinite loop**, first check if the input is an *empty string* and if it is, break out of the loop, otherwise get the users input containing *name*, *price* and *stock* in a single line, then split the line using `split()` method to get a list of inputed data. +5. Instead of appending each data to their own list, create a tuple called `item` containing `name`, `price` and `stock` in that particular order and append that to our `inventory` list we declared earlier. Print out each `inventory` element using `for` loop. +6. On to customer ordering items now. Keep `order` list and instead of storing only totals for each item, we will now store `item_name`, `item_quantity` and `line_total` in **tuple** called `line_item` and append that to our `order` list so our shop can better keep track of the orders. **Keep in mind** - tuples are *immutable* which means that you will have to reduce `stock` of the item by replacing entire tuple with new `stock` value. +7. Same as before, calculate the `total` for all the items bought, apply a 10% discount if the `total` is over 100. +8. In the end, print out the inventory, to make sure that the items are actually removed once bought. +9. Make sure your program runs, then commit the changes and push to Github ## What's Next {#next-lesson} -**Todo** \ No newline at end of file +Now that you have seen data structures that can contain duplicates, it's time to meet **set** - a unique data structure that does not allows for duplicates. \ No newline at end of file diff --git a/curriculum/05-data-structures/03-set.md b/curriculum/05-data-structures/03-set.md index 6cc032c..9253acd 100644 --- a/curriculum/05-data-structures/03-set.md +++ b/curriculum/05-data-structures/03-set.md @@ -7,7 +7,6 @@ lesson: true isDraft: true --- # Set -## Introduction {#introduction} A **set** in Python is unordered collection of unique elements. **Unordered** means it does not keep the order of the elements and **unique** means it does not allow duplicates. Its mostly used when removing duplicates from list or performing quick membership tests (checking to see if some element belongs to both sets). @@ -73,13 +72,22 @@ print("Difference:", set1 - set2) ``` :::explore[Learn more about Python Sets] -Learn more about sets in these materials: -* [Python built-in data types from RealPython](https://realpython.com/ref/builtin-types/set/) -* [Python data structures: set from official Python documentation](https://docs.python.org/3/tutorial/datastructures.html#sets) +Explore Python sets deeper by visiting this [built-in: set] article from **Real Python** (especially the part about additional methods which come in handy when working with sets). + +Remember you do not need to remember all the methods there are. Just read through them, to know they exist. ::: +## Exercise +Complete [[TODO] Exercise 07 — WorkingTitle](#) to practice sets. + ## Assignment {#assignment} -**Todo** +In this assigment our task is simple one. We need to track distinct *unsold* items so we can better prepare for the next day in our little shop. + +1. Open `main.py` file we have been working on. +2. Define a set for all **sold items** (`item[0]` of element in `order` list) and define a set of **all inventory items** (`item[0]` of element in `inventory` list) - you can use set coprehension to do this in one line or use a for loop to iterate over each item in the lists. +3. Create a variable `unsold_items` and set its value to be `sold_items` substracted from `all_inventory_items` +4. Print out items that did not have a sale today. +5. Confirm the program works, commit and push to Github ## What's Next {#next-lesson} -**Todo** \ No newline at end of file +Now that we covered index based data structures, it's time to meet **dictionary** which is unique in its *key-value* approach and is probably most used data structure (besides *lists*). \ No newline at end of file diff --git a/curriculum/05-data-structures/04-dictionary.md b/curriculum/05-data-structures/04-dictionary.md index 0ce1129..34516ac 100644 --- a/curriculum/05-data-structures/04-dictionary.md +++ b/curriculum/05-data-structures/04-dictionary.md @@ -7,7 +7,6 @@ lesson: true isDraft: true --- # Dictionary -## Introduction {#introduction} Dictionaries in Python are mutable and unordered collection data structure. **Mutable** meaning it can be modified after creating and **unordered** meaning it does not keep track of it's elements. Dictionaries are something special, usually called **key-value** data structure because of the way you store data inside them. You will certanly do a lot of work involving dictionaries in your python applications and its a very powerful concept, so let's get started. @@ -124,12 +123,27 @@ for key, value in mydict.items(): print(key, value) ``` +:::explore[Learn more about Python dicts] +Read this [built-in: dict](https://realpython.com/ref/builtin-types/dict/) article from **Real Python** and pay special attention to sections **dict Operators** and **dict Methods**. +Remember, just read through, you do not have to know it all. +::: -## Assignment {#assignment} - - -## Deepen Your Knowlege {#learn-more} +## Exercise +Complete [[TODO] Exercise 08 — WorkingTitle](#) to practice dictionaries. - -## What's Next {#next-lesson} \ No newline at end of file +## Assignment {#assignment} +In this assignment, we will completely eliminate list index tracking by refactoring our inventory into a dictionary, mapping each product name directly to its price and stock. + +1. Open `main.py` in our project directory. +2. Replace `inventory` list with an empty dictionary `{}`. +3. When reading users input, assign the item directly to dictionary `inventory`. + ```python + inventory[name] = {"price": price, "stock": stock} + ``` +4. In customer order, look up if item is in the inventory directly with `if item_name in inventory`, verify stock availability with `inventory[item_name]["stock"]` and update stock count in place with `inventory[item_name]["stock"] -= 1` and if stock reaches `0` then delete the item from the inventory using `del inventory[item_name]`. +5. Keep `order` as a list of tuples, and update the `unsold_items` variable to check between keys of the dictionary and tuple elements - use `inventory.keys()` to get a *tuple-like* object of dictionary keys that you can use in this case to substract `order` elements from keys of dictionary. +6. Test your application, make sure it works, commit and push to Github. + +## What's Next {#next-lesson} +We are now done with basic data structures in Python, next we move on to something even more fun and useful, kind of a super power in Python: **coprehensions** \ No newline at end of file diff --git a/curriculum/05-data-structures/05-comprehensions.md b/curriculum/05-data-structures/05-comprehensions.md new file mode 100644 index 0000000..e6e0b86 --- /dev/null +++ b/curriculum/05-data-structures/05-comprehensions.md @@ -0,0 +1,175 @@ +--- +id: comprehensions +title: Comprehensions +sidebar_label: Comprehensions +sidebar_position: 5 +lesson: true +isDraft: true +--- +# Comprehensions +Comprehensions in Python provide a short and clear way to create new sequences from existing iterable. Basically they are a *fancy* syntax for simple **for-loop** pattern. + +## Lesson Overview {#overview} +At the end of the lesson you will know: +* What are comprehensions in Python +* How to write `list`, `dict` or `set` comprehension +* How to use conditions in comprehensions + +The key to understanding list comprehensions is that they’re just `for-loops` over a collection expressed in a more terse and compact syntax. + +We will start with **list comprehension** as it is most common. + +## List Comprehension +Syntax for this looks like: +```python +[item for item in iterable] +``` + +Let's imagine we have a task of creating a list of **square** numbers from some other list of numbers. For example, let's assume we have a following list of numbers: +```python +nmb_list = [1, 2, 3, 4, 5, 6, 7, 8] +``` +To create a new list with **square** of all numbers in a list, we need to first get each element in the list and apply a mathematical operation on it. So it would look something like this: +```python interactive +nmb_list = [1, 2, 3, 4, 5, 6, 7, 8] +squared = [] +for nmb in nmb_list: + squared.append(nmb**2) + +print(squared) +``` +And the result is correct, but in Python, we can do better. Let's convert our `for-loop` to **list comprehension**. +```python interactive debug +nmb_list = [1, 2, 3, 4, 5, 6, 7, 8] +squared = [nmb**2 for nmb in nmb_list] +print(squared) +``` +Result is completely the same, but our code is simpler and more concise. In this simple example we may not see the benefit, but let's add a check there, to only collect **even** numbers. + +If we use **for-loop** we may do something like this. +```python interactive +nmb_list = [1, 2, 3, 4, 5, 6, 7, 8] +squared_even = [] +for nmb in nmb_list: + if nmb % 2 == 0: + squared_even.append(nmb ** 2) + +print(squared_even) +``` +If we use **list comprehension** it would look like this: +```python interactive debug +nmb_list = [1, 2, 3, 4, 5, 6, 7, 8] +squared_even = [nmb ** 2 for nmb in nmb_list if nmb % 2 == 0] +print(squared_even) +``` +The result is again, completely the same, but the syntax is shorter and more concise. + +Let's look at the final type of list comprehension, which will produce one value if the condition is `True` or something else if the condition is `False`. For example, let's say we need to produce a list, containing `True` if the number is even or `False` if its odd. + +In classic python **for-loop** style, we would do something like this: +```python interactive +nmb_list = [1, 2, 3, 4, 5, 6, 7, 8] +even_mask = [] +for nmb in nmb_list: + if nmb % 2 == 0: + even_mask.append(True) + else: + even_mask.append(False) +print(even_mask) +``` + +But Python let's us use its super power here also: +```python interactive debug +nmb_list = [1, 2, 3, 4, 5, 6, 7, 8] +even_mask = [True for nmb in nmb_list if nmb % 2 == 0 else False] +print(even_mask) +``` + +:::tip[Superpowers work with any comprehension] +`if condition` and `if condition else` works will all comprehensions and not just with lists, and they work in the same manner. +::: + +You do not need to worry about understanding **comprehensions** right away, but they become extremely useful the more you write your code. + +Now that we learned what are list comprehensions, let's look at **dictionary comprehensions** which are very similar in syntax but allows us to create dictionaries similarly. + +## Dictionary Comprehension +When creating a new dictionary using dictionary comprehension, you can perform various operations using expressions to determine the data (key and/or value) that will be stored in the new dictionary. + +Syntax for this looks like: +```python +{key: value for (key,value) in iterable} +``` + +To demonstrate this, let's imagine that you are building a currency converter. You would maybe have a dictionary representing prices in USD and need to convert them to EUR. In traditional **for-loop** you would do something like this: +```python interactive +EUR_CONV_RATE = 0.92 +prices_in_usd = {'pen': 4, 'book': 15, 'keyboard': 60} +prices_in_eur = {} +for name, price in prices_in_usd.items(): + prices_in_eur[name] = round(price * EUR_CONV_RATE, 2) +print(prices_in_eur) +``` +To use **dict comprehension** we would rewrite the above code to: +```python interactive debug +EUR_CONV_RATE = 0.92 +prices_in_usd = {'pen': 4, 'book': 15, 'keyboard': 60} + +prices_in_eur = {key: round(value * EUR_CONV_RATE, 2) for (key, value) in prices_in_usd.items()} + +print(prices_in_eur) +``` +:::tip +`round()` function rounds the numbers decimal point to specified number of places. It takes in `float` and a number of decimal places - an `integer`. +```python interactive +a = 43.24214213213 +b = round(a, 2) +print(b) +``` +::: + +:::info +In the above code we use `EUR_CONV_RATE` to declare **constant**. Constants are just variables, but are not supposed to be changed during running of your program. They are useful for declaring things that would not change during runtime of your program, and it's a convention in Python to write them in `ALL_CAPS`. Unlike some other languages, in Python, these are considered just like regular variables and Python will not stop you from changing them during runtime, so you need to consider this when writing your application. + +The golden rule is: +* If the variable will change during your application runtime, its just a variable and should be written as `variable_name`. +* If the variable will **not** change during your application runtime, then you can consider it a **constant** and write them as `VARIABLE_NAME`. + +Remember that this is just a convention and it is not a rule you *must* follow. +::: + +Now that we covered dictionary comprehensions, we can finally meet **set comprehensions**. + +## Set Comprehension +Set comprehension works best when you want a clean transformation, and you also want duplicates to disappear without extra effort. The syntax for **set comprehension** is: +```python +{expression for item in iterable} +``` + +For example, let's use our *squared* example from before: +```python interactive +nmb_list = [1, 2, 3, 4, 5, 6, 7, 8] +squared = {nmb ** 2 for nmb in nmb_list} +print(squared) +``` +We can also use conditionals to get only specific values: +```python interactive debug +nmb_list = [1, 2, 3, 4, 5, 6, 7, 8] +squared_even = {nmb ** 2 for nmb in nmb_list if nmb % 2 == 0} +print(squared_even) +``` + +:::warning +Comprehensions are very useful and can make your code smaller and easier to understand and reason about. But it also can make your code very difficult to read and understand. + +Use them with caution and remember: +* USE comprehensions while the code is readable +* DO NOT use comprehensions when the code starts to become unreadable and go back to **for-loop** for clarity. +::: + +## Exercise + +## Assignment {#assignment} + +## What's Next {#next-lesson} +Comprehensions are very useful in everyday life as a Python programmer, but there is one thing that is universal across all languages, so let's start a new chapter; *code organization*. First thing to learn are **functions** which enable us to write modular code.