├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── topic-request.md ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── LOCAL_USE.md ├── Projects └── Caesar Cipher.ipynb ├── Python-Notebooks ├── 1.Basic Python Syntax.ipynb ├── 2.Loops and Recursions.ipynb ├── 3.Strings, Lists, and Dictionaries.ipynb ├── 4.Regular Expressions.ipynb ├── 5.Working with Files and Directories.ipynb ├── 6.Working with CSV files.ipynb ├── Pandas Notebook.ipynb ├── Python-OOP.ipynb ├── data │ └── tarantino.csv ├── employee.csv ├── requirements.txt └── software.csv └── README.md /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/topic-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Topic Request 3 | about: Use this issue preset to add new topics to the checklist. 4 | title: "[Topic Request: topic]" 5 | labels: enhancement, help wanted 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Topic to be added** 11 | Name of the topic that you want to be added to the repository. [e.g. Regular Expressions in Python] 12 | 13 | **Why do you want the topic?** 14 | Is it something you feel difficult to understand? 15 | Are you unable to find proper documentation for the requested topic? 16 | [e.g. Regular Expressions are a complex topic and it is difficult for me to understand the official documentation for it.] 17 | 18 | **What do you want?** 19 | Describe what a notebook on the given topic should contain. 20 | [e.g. It should contain the basics of Regular Expression and also provide specific examples of how we can use complex expressions or things such as backreferencing and capturing groups.] 21 | 22 | **How will it help others?** 23 | Describe how a notebook on the given topic will be beneficial for the community at large. 24 | [e.g. Regular Expressions are pretty much needed by most people who work with data and I think a large number of people will benefit if a notebook with clear examples is made available on the topic.] 25 | 26 | **Additional Comments** 27 | Any additional comments regarding the request. 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Please take a moment to review this document in order to make the contribution process easy and 4 | effective for everyone involved. 5 | 6 | Following these guidelines helps to communicate that you respect the time of the developers managing 7 | and developing this open source repo. In return, they should reciprocate that respect in addressing 8 | your issue or assessing your pull requests. 9 | 10 | ## Goal 11 | 12 | The repository is meant to work as a learning tool for new programmers and also as a cheat sheet for 13 | other intermediate developers. The repository is dedicated to python and also coding in general. 14 | 15 | ## Using the Issue Tracker 16 | 17 | The issue tracker is the preferred channel for bug reports, adding content and submitting pull requests, but please 18 | respect the following restrictions: 19 | * Please do not use the issue tracker for personal support requests. If you need any help in understanding 20 | the content or code of any specific file, contact the creator of the file, preferably via email. 21 | * Please do not derail or troll issues. Keep the discussion on topic and respect the opinion of others. 22 | 23 | ## Adding and Requesting content 24 | 25 | The [README](https://github.com/aceking007/Byte-Sized-Code/blob/master/README.md) file contains a checklist 26 | for content that is prepared and content that is to be prepared. Do add to the checklists (and also raise an issue) 27 | if you want a notebook on some specific topic or feel free to work on some of the unchecked topics by creating a 28 | self-explanatory jupyter notebook. 29 | 30 | Please **do** raise an issue before working on a specific topic. This prevents multiple people from working individually on a 31 | single topic. Feel free to contribute in groups to a single notebook. This encourages community participation and reduces 32 | the amount of workload or stress on a single person. 33 | 34 | ## Bug Reports 35 | 36 | A bug is a *demonstrable problem* that is caused by the code in the repository. 37 | Good bug reports are extremely helpful - thank you! 38 | 39 | Guidelines for bug reports: 40 | 1. **Use the GitHub issue search** - check if the issue has already been reported. 41 | 2. **Check if the issue has been fixed** - try to reproduce it using the latest master or development branch in the repo. 42 | 3. **Isolate the problem** - make sure that the code in the repository is *definitely* responsible for the issue. 43 | 44 | A good bug report shouldn't leave others needing to chase you up for more information. 45 | Please try to be as detailed as possible in your report. 46 | 47 | ## Pull Requests 48 | 49 | Good pull requests - patches, improvements, new features - are a fantastic help. They should remain 50 | focused in scope and avoid containing unrelated commits. 51 | 52 | **Please ask first** before embarking on any significant pull request (e.g. code refactoring, adding examples or files), 53 | otherwise you risk spending a lot of time working on something that the developers might not want to merge into the project. 54 | Please adhere to the coding conventions used throughout the project (indentation, comments, etc.). 55 | 56 | Adhering to the following process is the best way to get your work merged: 57 | 58 | 1. [Fork](https://help.github.com/fork-a-repo) the repo, clone your fork, and configure the remotes: 59 | 60 | ```bash 61 | # Clone your fork of the repo into the current directory 62 | git clone https://github.com// 63 | # Navigate to the newly cloned directory 64 | cd 65 | # Assign the original repo to a remote called "upstream" 66 | git remote add upstream https://github.com// 67 | ``` 68 | 69 | 2. If you cloned a while ago, get the latest changes from upstream: 70 | 71 | ```bash 72 | git checkout 73 | git pull upstream 74 | ``` 75 | 76 | 3. Create a new topic branch (off the main project development branch) to 77 | contain your feature, change, or fix: 78 | 79 | ```bash 80 | git checkout -b 81 | ``` 82 | 83 | 4. Commit your changes in logical chunks. Please adhere to these [git commit 84 | message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) 85 | or your code is unlikely be merged into the main project. Use Git's 86 | [interactive rebase](https://help.github.com/articles/interactive-rebase) 87 | feature to tidy up your commits before making them public. 88 | 89 | 5. Locally merge (or rebase) the upstream development branch into your topic branch: 90 | 91 | ```bash 92 | git pull [--rebase] upstream 93 | ``` 94 | 95 | 6. Push your topic branch up to your fork: 96 | 97 | ```bash 98 | git push origin 99 | ``` 100 | 101 | 10. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) 102 | with a clear title and description. 103 | 104 | 105 | ## License 106 | 107 | Any code/documentation that you contribute to the project will be available as open-source under the MIT License. 108 | 109 | ## Credits 110 | 111 | The above document was adapted from the [contributing doc](https://github.com/roots/guidelines/blob/master/CONTRIBUTING.md) of the [roots](https://github.com/roots) project. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Arpit Omprakash 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LOCAL_USE.md: -------------------------------------------------------------------------------- 1 | # Running the notebooks on your local machine 2 | 3 | Follow the steps outlined below to run the repo in your local machine configured with [Python 3](https://www.python.org/download/releases/3.0/). 4 | 5 | 1. Create and Activate a Virtual Environment 6 | 7 | This step creates a virtual environment where you can install the necessary python packages to run the notebooks and other associated projects. 8 | This step is optional (but we recommend you follow this, or make sure you understand the consequences of not following this step). 9 | 10 | Creating the virtual environment. 11 | On macOS and Linux: 12 | ```bash 13 | python3 -m venv env 14 | ``` 15 | 16 | On Windows: 17 | ``` 18 | py -m venv env 19 | ``` 20 | 21 | Activating the virtual environment. 22 | On macOS and Linux: 23 | ```bash 24 | source env/bin/activate 25 | ``` 26 | 27 | On Windows: 28 | ``` 29 | .\env\Scripts\activate 30 | ``` 31 | 32 | 2. Install the Requirements 33 | 34 | This step installs the required packages and dependencies before you can fire up the notebook. 35 | Run the following after activating the virtual environment: 36 | ```bash 37 | pip install -r requirements.txt 38 | ``` 39 | 40 | 3. Boot up Jupyter 41 | 42 | You should have installed Jupyter and other dependencies to run the notebooks after the last step. 43 | Start the jupyter notebook server from the CLI. 44 | ```bash 45 | jupyter notebook 46 | ``` 47 | 48 | 4. Enjoy 49 | 50 | [Here](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html) is a handy guide to working with jupyter notebooks. 51 | Feel free to email or contact if there is any other issue. -------------------------------------------------------------------------------- /Projects/Caesar Cipher.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Caesar Cipher\n", 8 | "\n", 9 | "**By Arpit Omprakash, Byte Sized Code**" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "## What is Caesar Cipher?\n", 17 | "\n", 18 | "The Caesar Cipher is one of the simplest [ciphers](https://en.wikipedia.org/wiki/Cipher) in cryptography. \n", 19 | "It is used to encrypt or decrypt messages/texts between two parties. \n", 20 | "It is a kind of **Monoalphabetic Substitution cipher.**\n", 21 | "\n", 22 | "A [Substitution cipher](https://en.wikipedia.org/wiki/Substitution_cipher) is a simple cipher where some characters of the plaintext are replaced by specific characters to produce the ciphertext.\n", 23 | "\n", 24 | "To encrypt text using classic Caesar cipher, we just shift the alphaber by 3 and substitute the values. For example, A is replaced by D, B -> E, C -> F, and so on, till Y -> B and Z -> C. \n", 25 | "Its really simple. Let's have a look at a simple example." 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "## Working Example\n", 33 | "\n", 34 | "Lets take a simple example. \n", 35 | "Our enemy is stationed in a palace in a valley. Unsuspecting of any attach they are enjoying in their palace. Our army is at one of the hill peaks near the valley and our allies are at the other end on the opposite hill. \n", 36 | "We want to encrypt the phrase **ATTACK AT ONCE** and send it to our allies on the other side, so that we both can start the attack at the same time and crush our enemy from both sides. \n", 37 | "We disregard spaces as we don't have any method to encrypt spaces using the Caesar Cipher, thus, the plaintext becomes **ATTACKATONCE** \n", 38 | "\n", 39 | "To encrypt using the traditional Caesar Cipher, we shift alphabets to the right by 3 places. Thus, we need to make the following changes: \n", 40 | "- A -> D\n", 41 | "- T -> W\n", 42 | "- C -> F\n", 43 | "- K -> N\n", 44 | "- O -> R\n", 45 | "- N -> Q\n", 46 | "- E -> H \n", 47 | "Making the necessary changes: \n", 48 | "plaintext - **ATTACKATONCE** \n", 49 | "encrypted - **DWWDFNDWRQFH** \n", 50 | "\n", 51 | "Once the message is delivered on the other side, our allies (who know how to encrypt and decrypt) can then just reverse shift the alphabet by 3 places to get the message that we sent. \n", 52 | "The message they receive: **DWWDFNDWRQFH**\n", 53 | "They make the following changes: \n", 54 | "- D -> A\n", 55 | "- W -> T\n", 56 | "- F -> C\n", 57 | "- N -> K\n", 58 | "- R -> O\n", 59 | "- Q -> N\n", 60 | "- H -> E \n", 61 | "Making the changes: \n", 62 | "encrypted message - **DWWDFNDWRQFH** \n", 63 | "decrypted message - **ATTACKATONCE**\n", 64 | "\n", 65 | "The allies then add the necessary spaces, look at the message and launch their attack! Together, we defeat the enemies and have a nice day hanging out at their palace.\n", 66 | "\n", 67 | "Wikipedia has another [working example](https://en.wikipedia.org/wiki/Caesar_cipher#Example) if you want to check it out." 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "## What are we going to do?\n", 75 | "\n", 76 | "We will code two simple functions that will help us encrypt and decrypt text using the Caesar Cipher. As the project is aimed at beginners, we will be using conventions and code that is easy to understand but not high performance. \n", 77 | "Once you are familiar and comfortable with the code, I would suggest you to try to improve on it." 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "## Actual Code" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "### Data structure for conversion\n", 92 | "\n", 93 | "To make things simpler, we will use dictionaries to use for the encryption and decryption process. \n", 94 | "We will have one dictionary for encryption and another for decryption." 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": 1, 100 | "metadata": {}, 101 | "outputs": [ 102 | { 103 | "name": "stdout", 104 | "output_type": "stream", 105 | "text": [ 106 | "{'A': 'D', 'B': 'E', 'C': 'F', 'D': 'G', 'E': 'H', 'F': 'I', 'G': 'J', 'H': 'K', 'I': 'L', 'J': 'M', 'K': 'N', 'L': 'O', 'M': 'P', 'N': 'Q', 'O': 'R', 'P': 'S', 'Q': 'T', 'R': 'U', 'S': 'V', 'T': 'W', 'U': 'X', 'V': 'Y', 'W': 'Z', 'X': 'A', 'Y': 'B', 'Z': 'C'}\n" 107 | ] 108 | } 109 | ], 110 | "source": [ 111 | "# Encryption dictionary\n", 112 | "encrypt_key = {\"A\": \"D\", \"B\": \"E\", \"C\": \"F\", \"D\": \"G\", \"E\": \"H\", \"F\": \"I\", \"G\": \"J\", \n", 113 | " \"H\": \"K\", \"I\": \"L\", \"J\": \"M\", \"K\": \"N\", \"L\": \"O\", \"M\": \"P\", \"N\": \"Q\", \n", 114 | " \"O\": \"R\", \"P\": \"S\", \"Q\": \"T\", \"R\": \"U\", \"S\": \"V\", \"T\": \"W\", \"U\": \"X\", \n", 115 | " \"V\": \"Y\", \"W\": \"Z\", \"X\": \"A\", \"Y\": \"B\", \"Z\": \"C\"}\n", 116 | "print(encrypt_key)" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 2, 122 | "metadata": {}, 123 | "outputs": [ 124 | { 125 | "name": "stdout", 126 | "output_type": "stream", 127 | "text": [ 128 | "{'D': 'A', 'E': 'B', 'F': 'C', 'G': 'D', 'H': 'E', 'I': 'F', 'J': 'G', 'K': 'H', 'L': 'I', 'M': 'J', 'N': 'K', 'O': 'L', 'P': 'M', 'Q': 'N', 'R': 'O', 'S': 'P', 'T': 'Q', 'U': 'R', 'V': 'S', 'W': 'T', 'X': 'U', 'Y': 'V', 'Z': 'W', 'A': 'X', 'B': 'Y', 'C': 'Z'}\n" 129 | ] 130 | } 131 | ], 132 | "source": [ 133 | "# Decryption dictionary\n", 134 | "# Just reverse the encryption dictionary\n", 135 | "decrypt_key = {value: key for key, value in encrypt_key.items()}\n", 136 | "print(decrypt_key)" 137 | ] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": {}, 142 | "source": [ 143 | "### Encryption\n", 144 | "\n", 145 | "We will write one function to help with the encryption process. \n", 146 | "The function will take in the plaintext (string) as input and return the encrypted text (string) as output." 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": 3, 152 | "metadata": {}, 153 | "outputs": [], 154 | "source": [ 155 | "# Encryption function\n", 156 | "def encrypt(plaintext):\n", 157 | " # Initialize an empty string\n", 158 | " encrypted = \"\"\n", 159 | " # We use .upper() to convert all characters to uppercase as our dictionary supports uppercase only\n", 160 | " for character in plaintext.upper():\n", 161 | " # Add the encrypted character to the initialized string\n", 162 | " encrypted += encrypt_key[character]\n", 163 | " # Return the encrypted string\n", 164 | " return encrypted" 165 | ] 166 | }, 167 | { 168 | "cell_type": "markdown", 169 | "metadata": {}, 170 | "source": [ 171 | "We can use the function to encrypt the initial example phrase, \"ATTACKATONCE\" and check if it matches the answer that we got above." 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": 4, 177 | "metadata": {}, 178 | "outputs": [ 179 | { 180 | "data": { 181 | "text/plain": [ 182 | "'DWWDFNDWRQFH'" 183 | ] 184 | }, 185 | "execution_count": 4, 186 | "metadata": {}, 187 | "output_type": "execute_result" 188 | } 189 | ], 190 | "source": [ 191 | "encrypt(\"ATTACKATONCE\")" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "Yes it does! Hooray! We've done half of the job, the other part is quite as simple too. \n", 199 | "We just need a decryption function." 200 | ] 201 | }, 202 | { 203 | "cell_type": "markdown", 204 | "metadata": {}, 205 | "source": [ 206 | "### Decryption\n", 207 | "\n", 208 | "The decryption function is the inverse of the encryption function. \n", 209 | "It takes in an encrypted string and converts it to the corresponding plaintext (string). \n", 210 | "The function will be quite similar to the encryption function." 211 | ] 212 | }, 213 | { 214 | "cell_type": "code", 215 | "execution_count": 5, 216 | "metadata": {}, 217 | "outputs": [], 218 | "source": [ 219 | "# Decryption function\n", 220 | "def decrypt(encrypted):\n", 221 | " # Initialize the plaintext string\n", 222 | " plaintext = \"\"\n", 223 | " # Same logic for using the upper function\n", 224 | " for character in encrypted.upper():\n", 225 | " plaintext += decrypt_key[character]\n", 226 | " # Return the final plaintext\n", 227 | " return plaintext" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": {}, 233 | "source": [ 234 | "Now that we have a function for decryption, lets test it out using the encrypted text we got above:" 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "execution_count": 6, 240 | "metadata": {}, 241 | "outputs": [ 242 | { 243 | "data": { 244 | "text/plain": [ 245 | "'ATTACKATONCE'" 246 | ] 247 | }, 248 | "execution_count": 6, 249 | "metadata": {}, 250 | "output_type": "execute_result" 251 | } 252 | ], 253 | "source": [ 254 | "decrypt('DWWDFNDWRQFH')" 255 | ] 256 | }, 257 | { 258 | "cell_type": "markdown", 259 | "metadata": {}, 260 | "source": [ 261 | "Yay! We got our initial value for \"ATTACKATONCE\" from the encrypted text!" 262 | ] 263 | }, 264 | { 265 | "cell_type": "markdown", 266 | "metadata": {}, 267 | "source": [ 268 | "So, that's all for the script. \n", 269 | "You can surely compile it into a single pytho file. \n", 270 | "I'd suggest improving on the code a bit once you fully understand it (look below for other interesting thing to try out). \n", 271 | "If this was your first project after learning Python, then congratulations on completing it! \n", 272 | "Watchout for more projects to come and keep coding meanwhile!" 273 | ] 274 | }, 275 | { 276 | "cell_type": "markdown", 277 | "metadata": {}, 278 | "source": [ 279 | "### What to do next?\n", 280 | "\n", 281 | "First of all, compile it into a single script and try to make it a commandline tool. \n", 282 | "Where you can ask the user for inputs and then return the corresponding encrypted and decrypted texts. \n", 283 | "\n", 284 | "Here are a few ideas of improving on the project (and making some similar projects):\n", 285 | "- Rework the current data structure for conversions (dictionary) and implement a modulo based conversion\n", 286 | "- Expand the project to include any number of character shifts from 1 to 26 (we just worked with a shift of 3)\n", 287 | "- If Cryptography interests you (like me), try coding some other simple ciphers using python. Here are two to get you started:\n", 288 | " - [ROT 13](https://en.wikipedia.org/wiki/ROT13)\n", 289 | " - [Vigenere Cipher](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher)" 290 | ] 291 | } 292 | ], 293 | "metadata": { 294 | "kernelspec": { 295 | "display_name": "Python 3", 296 | "language": "python", 297 | "name": "python3" 298 | }, 299 | "language_info": { 300 | "codemirror_mode": { 301 | "name": "ipython", 302 | "version": 3 303 | }, 304 | "file_extension": ".py", 305 | "mimetype": "text/x-python", 306 | "name": "python", 307 | "nbconvert_exporter": "python", 308 | "pygments_lexer": "ipython3", 309 | "version": "3.8.3" 310 | } 311 | }, 312 | "nbformat": 4, 313 | "nbformat_minor": 4 314 | } 315 | -------------------------------------------------------------------------------- /Python-Notebooks/1.Basic Python Syntax.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Basic Python Syntax\n", 8 | "\n", 9 | "**By Arpit Omprakash, Byte Sized Code**" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "### Basic Data Types \n", 17 | "\n", 18 | "While programming, we work with data, and data comes in all kinds of flavours and *types*. \n", 19 | "There are a few basic data types in python that are used to store and manipulate any kind of data that we want to work with.\n", 20 | "\n", 21 | "Python supports the following basic (a.k.a primitive) data types: \n", 22 | "- string:\n", 23 | " - used to store characters\n", 24 | " - always enclosed in quote marks (\" or ')\n", 25 | " - denoted as `str`\n", 26 | "- integer:\n", 27 | " - used to store integers (numbers without a fractional part)\n", 28 | " - can be positive or negative\n", 29 | " - denoted as `int`\n", 30 | "- float:\n", 31 | " - used to store real numbers\n", 32 | " - denoted by `float`\n", 33 | "- boolean:\n", 34 | " - used to store a True/False value\n", 35 | " - denoted by `bool`\n", 36 | " \n", 37 | "We can use the inbuilt `type` function (more on functions later) to get the datatype of a given chunk of data. " 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 129, 43 | "metadata": {}, 44 | "outputs": [ 45 | { 46 | "name": "stdout", 47 | "output_type": "stream", 48 | "text": [ 49 | "\n" 50 | ] 51 | } 52 | ], 53 | "source": [ 54 | "print(type(\"name\"))" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 130, 60 | "metadata": {}, 61 | "outputs": [ 62 | { 63 | "name": "stdout", 64 | "output_type": "stream", 65 | "text": [ 66 | "\n" 67 | ] 68 | } 69 | ], 70 | "source": [ 71 | "print(type(2))" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 131, 77 | "metadata": {}, 78 | "outputs": [ 79 | { 80 | "name": "stdout", 81 | "output_type": "stream", 82 | "text": [ 83 | "\n" 84 | ] 85 | } 86 | ], 87 | "source": [ 88 | "print(type(8.3))" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 132, 94 | "metadata": {}, 95 | "outputs": [ 96 | { 97 | "name": "stdout", 98 | "output_type": "stream", 99 | "text": [ 100 | "\n" 101 | ] 102 | } 103 | ], 104 | "source": [ 105 | "print(type(True))" 106 | ] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": {}, 111 | "source": [ 112 | "### Operators\n", 113 | "\n", 114 | "Now that we know how to store data using the appropriate types, we would eventually like to manipulate the data. \n", 115 | "Python provides many operators that can be used to manipulate data. \n", 116 | "Here are the most commonly used operators in python:" 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": {}, 122 | "source": [ 123 | "\\\"+\" addition operator\n", 124 | "- used to add two values" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": 133, 130 | "metadata": {}, 131 | "outputs": [ 132 | { 133 | "name": "stdout", 134 | "output_type": "stream", 135 | "text": [ 136 | "6\n" 137 | ] 138 | } 139 | ], 140 | "source": [ 141 | "print(2 + 4)" 142 | ] 143 | }, 144 | { 145 | "cell_type": "markdown", 146 | "metadata": {}, 147 | "source": [ 148 | "\"/\" division operator\n", 149 | "- used to divide one value by the other" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": 134, 155 | "metadata": {}, 156 | "outputs": [ 157 | { 158 | "name": "stdout", 159 | "output_type": "stream", 160 | "text": [ 161 | "1.5\n" 162 | ] 163 | } 164 | ], 165 | "source": [ 166 | "print(3.0 / 2.0)" 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "\"\\*\" multiplication operator\n", 174 | "- used to multiply two values" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": 135, 180 | "metadata": {}, 181 | "outputs": [ 182 | { 183 | "name": "stdout", 184 | "output_type": "stream", 185 | "text": [ 186 | "20\n" 187 | ] 188 | } 189 | ], 190 | "source": [ 191 | "print(10 * 2)" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "\"-\" subtraction operator\n", 199 | "- used to subtract one value from another" 200 | ] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": 136, 205 | "metadata": {}, 206 | "outputs": [ 207 | { 208 | "name": "stdout", 209 | "output_type": "stream", 210 | "text": [ 211 | "2\n" 212 | ] 213 | } 214 | ], 215 | "source": [ 216 | "print(3 - 1)" 217 | ] 218 | }, 219 | { 220 | "cell_type": "markdown", 221 | "metadata": {}, 222 | "source": [ 223 | "\"%\" modulo operator\n", 224 | "- returns the remainder of a division between the two values" 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "execution_count": 137, 230 | "metadata": {}, 231 | "outputs": [ 232 | { 233 | "name": "stdout", 234 | "output_type": "stream", 235 | "text": [ 236 | "0\n" 237 | ] 238 | } 239 | ], 240 | "source": [ 241 | "print(25 % 5)" 242 | ] 243 | }, 244 | { 245 | "cell_type": "markdown", 246 | "metadata": {}, 247 | "source": [ 248 | "\"\\*\\*\" exponentiation operator\n", 249 | "- raises the first number to the power of the second number" 250 | ] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "execution_count": 138, 255 | "metadata": {}, 256 | "outputs": [ 257 | { 258 | "name": "stdout", 259 | "output_type": "stream", 260 | "text": [ 261 | "32\n" 262 | ] 263 | } 264 | ], 265 | "source": [ 266 | "print(2 ** 5)" 267 | ] 268 | }, 269 | { 270 | "cell_type": "markdown", 271 | "metadata": {}, 272 | "source": [ 273 | "\"//\" floor division operator\n", 274 | "- returns the quotient of the division of the two numbers" 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": 139, 280 | "metadata": {}, 281 | "outputs": [ 282 | { 283 | "name": "stdout", 284 | "output_type": "stream", 285 | "text": [ 286 | "11\n" 287 | ] 288 | } 289 | ], 290 | "source": [ 291 | "print(34 // 3)" 292 | ] 293 | }, 294 | { 295 | "cell_type": "markdown", 296 | "metadata": {}, 297 | "source": [ 298 | "**Operators and strings**\n", 299 | "\n", 300 | "A few operators can also be used with strings. \n", 301 | "- the addition operator concatenates two strings to form a bigger string\n", 302 | "- the multiplication operator repeats a string n times (where n is the other operant)" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 140, 308 | "metadata": {}, 309 | "outputs": [ 310 | { 311 | "name": "stdout", 312 | "output_type": "stream", 313 | "text": [ 314 | "hello world\n" 315 | ] 316 | } 317 | ], 318 | "source": [ 319 | "print(\"hello \" + \"world\")" 320 | ] 321 | }, 322 | { 323 | "cell_type": "code", 324 | "execution_count": 141, 325 | "metadata": {}, 326 | "outputs": [ 327 | { 328 | "name": "stdout", 329 | "output_type": "stream", 330 | "text": [ 331 | "hellohellohello\n" 332 | ] 333 | } 334 | ], 335 | "source": [ 336 | "print(\"hello\" * 3)" 337 | ] 338 | }, 339 | { 340 | "cell_type": "markdown", 341 | "metadata": {}, 342 | "source": [ 343 | "**NOTE:** It should be noted that operators only work with the same data type. For example, we cannot add an integer to a string." 344 | ] 345 | }, 346 | { 347 | "cell_type": "code", 348 | "execution_count": 142, 349 | "metadata": {}, 350 | "outputs": [ 351 | { 352 | "ename": "TypeError", 353 | "evalue": "can only concatenate str (not \"int\") to str", 354 | "output_type": "error", 355 | "traceback": [ 356 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 357 | "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", 358 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"hello \"\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 359 | "\u001b[1;31mTypeError\u001b[0m: can only concatenate str (not \"int\") to str" 360 | ] 361 | } 362 | ], 363 | "source": [ 364 | "print(\"hello \" + 2)" 365 | ] 366 | }, 367 | { 368 | "cell_type": "markdown", 369 | "metadata": {}, 370 | "source": [ 371 | "### Type conversions\n", 372 | "\n", 373 | "As mentioned above, we can't mix data types while operating on them. This is a half truth. \n", 374 | "We can mix some operators to a certain level. For example:" 375 | ] 376 | }, 377 | { 378 | "cell_type": "code", 379 | "execution_count": 143, 380 | "metadata": {}, 381 | "outputs": [ 382 | { 383 | "name": "stdout", 384 | "output_type": "stream", 385 | "text": [ 386 | "4.0\n" 387 | ] 388 | } 389 | ], 390 | "source": [ 391 | "print(2 + 2.0)" 392 | ] 393 | }, 394 | { 395 | "cell_type": "markdown", 396 | "metadata": {}, 397 | "source": [ 398 | "Here we added an integer to a float and we didn't get an error! \n", 399 | "\n", 400 | "What happened here you ask? \n", 401 | "Something called an **implicit type conversion**. \n", 402 | "As floats can also contain integer values, Python converts the integer data type to a float data type before carrying out the addition. This can be noted from the fact that the result of the operation is a float." 403 | ] 404 | }, 405 | { 406 | "cell_type": "code", 407 | "execution_count": 144, 408 | "metadata": {}, 409 | "outputs": [ 410 | { 411 | "name": "stdout", 412 | "output_type": "stream", 413 | "text": [ 414 | "\n" 415 | ] 416 | } 417 | ], 418 | "source": [ 419 | "result = 2 + 2.0\n", 420 | "print(type(result))" 421 | ] 422 | }, 423 | { 424 | "cell_type": "markdown", 425 | "metadata": {}, 426 | "source": [ 427 | "However, for some data types, Python does not allow implicit conversion. \n", 428 | "We can however still convert the data (if need arises) by an **explicit type conversion** syntax/function. \n", 429 | "This can be seen in the following example." 430 | ] 431 | }, 432 | { 433 | "cell_type": "code", 434 | "execution_count": 145, 435 | "metadata": {}, 436 | "outputs": [ 437 | { 438 | "ename": "TypeError", 439 | "evalue": "can only concatenate str (not \"int\") to str", 440 | "output_type": "error", 441 | "traceback": [ 442 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 443 | "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", 444 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"number \"\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m23\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 445 | "\u001b[1;31mTypeError\u001b[0m: can only concatenate str (not \"int\") to str" 446 | ] 447 | } 448 | ], 449 | "source": [ 450 | "print(\"number \" + 23)" 451 | ] 452 | }, 453 | { 454 | "cell_type": "code", 455 | "execution_count": 146, 456 | "metadata": {}, 457 | "outputs": [ 458 | { 459 | "name": "stdout", 460 | "output_type": "stream", 461 | "text": [ 462 | "number 23\n" 463 | ] 464 | } 465 | ], 466 | "source": [ 467 | "print(\"number \" + str(23))" 468 | ] 469 | }, 470 | { 471 | "cell_type": "markdown", 472 | "metadata": {}, 473 | "source": [ 474 | "The `str` function converts a given data type to string data type." 475 | ] 476 | }, 477 | { 478 | "cell_type": "markdown", 479 | "metadata": {}, 480 | "source": [ 481 | "### Variables\n", 482 | "\n", 483 | "It is very likely that any program that you will write will have some values that will change over time or even over the course of your whole program (or script). \n", 484 | "We can store such values in variables. \n", 485 | "You can think of variables as containers to store data.\n", 486 | "\n", 487 | "Values are *assigned* to variables via an assignment operator (like =).\n", 488 | "\n", 489 | "In the following example, we have created two variables called `length` and `breadth`. \n", 490 | "We can store different values in the variables and then later use them to carry out other functions or operations without even knowing what exact value the variable contains!" 491 | ] 492 | }, 493 | { 494 | "cell_type": "code", 495 | "execution_count": 147, 496 | "metadata": {}, 497 | "outputs": [ 498 | { 499 | "name": "stdout", 500 | "output_type": "stream", 501 | "text": [ 502 | "200\n" 503 | ] 504 | } 505 | ], 506 | "source": [ 507 | "length = 10\n", 508 | "breadth = 20\n", 509 | "area = length * breadth\n", 510 | "print(area)" 511 | ] 512 | }, 513 | { 514 | "cell_type": "markdown", 515 | "metadata": {}, 516 | "source": [ 517 | "Now lets change the value of the `breadth` variable and calculate the area again." 518 | ] 519 | }, 520 | { 521 | "cell_type": "code", 522 | "execution_count": 148, 523 | "metadata": {}, 524 | "outputs": [ 525 | { 526 | "name": "stdout", 527 | "output_type": "stream", 528 | "text": [ 529 | "100\n" 530 | ] 531 | } 532 | ], 533 | "source": [ 534 | "breadth = 10\n", 535 | "area = length * breadth\n", 536 | "print(area)" 537 | ] 538 | }, 539 | { 540 | "cell_type": "markdown", 541 | "metadata": {}, 542 | "source": [ 543 | "**NOTE: Variable Nomenclature**\n", 544 | "\n", 545 | "There are certain restrictions that are applied while creating variables in python: \n", 546 | "- we can't use keywords or built-in function names as variable names, e.g., `print`, `int` and `str` are not valid variable names.\n", 547 | "- variable names can't contain spaces, e.g., `new variable` is not valid\n", 548 | "- variable names should start with letters or underscores, e.g., `my_var` or `_var` are valid\n", 549 | "- variable names can contain only numbers, letters, or underscores, e.g., `_my_var_1` is a valid name" 550 | ] 551 | }, 552 | { 553 | "cell_type": "markdown", 554 | "metadata": {}, 555 | "source": [ 556 | "### Functions\n", 557 | "\n", 558 | "In the previous section we have mentioned and used certain functions like `str()`, `type()` and `print()`. \n", 559 | "But what exactly are functions? \n", 560 | "Functions are snippets of code that can be called upon to carry out specific tasks. \n", 561 | "In the following example, we create a `show()` function that prints or \"shows\" a predefined greeting to us." 562 | ] 563 | }, 564 | { 565 | "cell_type": "code", 566 | "execution_count": 149, 567 | "metadata": {}, 568 | "outputs": [], 569 | "source": [ 570 | "def show():\n", 571 | " print(\"Welcome humanling!\")" 572 | ] 573 | }, 574 | { 575 | "cell_type": "markdown", 576 | "metadata": {}, 577 | "source": [ 578 | "Note the syntax while creating (also called defining) a function. \n", 579 | "The function starts with a `def` keyword followed by the name and a parentheses. \n", 580 | "The first line must end with a colon (:) to indicate that it is a special kind of python statement. \n", 581 | "The next part of the code contains all the instructions for the function. These are indented to indicated that the instructions belong to the defined function. Remember, **whitespace and indentation is critical in python**.\n", 582 | "\n", 583 | "We covered all the steps for creating a function, then why doesn't it print anything? \n", 584 | "We need to call a function to make it work. The following cell calls the `show` function we defined above." 585 | ] 586 | }, 587 | { 588 | "cell_type": "code", 589 | "execution_count": 150, 590 | "metadata": {}, 591 | "outputs": [ 592 | { 593 | "name": "stdout", 594 | "output_type": "stream", 595 | "text": [ 596 | "Welcome humanling!\n" 597 | ] 598 | } 599 | ], 600 | "source": [ 601 | "show()" 602 | ] 603 | }, 604 | { 605 | "cell_type": "markdown", 606 | "metadata": {}, 607 | "source": [ 608 | "Now we get the output!\n", 609 | "\n", 610 | "Functions can even take some parameters (or arguments) to carry out more specific tasks. \n", 611 | "Parameters are defined by writing variables for the parameters inside the parenthesis while defining a function. \n", 612 | "For example, the following function takes in a string called `name` as an argument and then prints a specialized greeting." 613 | ] 614 | }, 615 | { 616 | "cell_type": "code", 617 | "execution_count": 151, 618 | "metadata": {}, 619 | "outputs": [], 620 | "source": [ 621 | "def greet(name):\n", 622 | " print(\"Welcome \"+ name + \"!\")" 623 | ] 624 | }, 625 | { 626 | "cell_type": "code", 627 | "execution_count": 152, 628 | "metadata": {}, 629 | "outputs": [ 630 | { 631 | "name": "stdout", 632 | "output_type": "stream", 633 | "text": [ 634 | "Welcome Arpit!\n" 635 | ] 636 | } 637 | ], 638 | "source": [ 639 | "greet(\"Arpit\")" 640 | ] 641 | }, 642 | { 643 | "cell_type": "markdown", 644 | "metadata": {}, 645 | "source": [ 646 | "To make things more interesting, functions can take in more than one argument at a time." 647 | ] 648 | }, 649 | { 650 | "cell_type": "code", 651 | "execution_count": 153, 652 | "metadata": {}, 653 | "outputs": [], 654 | "source": [ 655 | "def greeting(name, department):\n", 656 | " print(\"Welcome \" + name + \"!\")\n", 657 | " print(\"You are a part of the \" + department + \" department.\")" 658 | ] 659 | }, 660 | { 661 | "cell_type": "code", 662 | "execution_count": 154, 663 | "metadata": {}, 664 | "outputs": [ 665 | { 666 | "name": "stdout", 667 | "output_type": "stream", 668 | "text": [ 669 | "Welcome Tom!\n", 670 | "You are a part of the accounting department.\n" 671 | ] 672 | } 673 | ], 674 | "source": [ 675 | "greeting(\"Tom\", \"accounting\")" 676 | ] 677 | }, 678 | { 679 | "cell_type": "markdown", 680 | "metadata": {}, 681 | "source": [ 682 | "Up until now we have just printed statements from our functions, but we can do so much more! \n", 683 | "We give values to a function by providing arguments. But how do we get values back from a function? \n", 684 | "We use what are called `return` statements. \n", 685 | "A `return` statement returns values from a function.\n", 686 | "\n", 687 | "Earlier we used the breadth and length to calculate area of a rectangle. Do you recall we had to repeat the `area = length * breadth` to calculate area again after changing the value of breadth. Doing this for each change is a cumbersome task. \n", 688 | "Now we have enough knowledge to create a basic function that will calculate the area for us if we provide a length and breadth value to it." 689 | ] 690 | }, 691 | { 692 | "cell_type": "code", 693 | "execution_count": 155, 694 | "metadata": {}, 695 | "outputs": [], 696 | "source": [ 697 | "def area(length, breadth):\n", 698 | " return length * breadth" 699 | ] 700 | }, 701 | { 702 | "cell_type": "code", 703 | "execution_count": 156, 704 | "metadata": {}, 705 | "outputs": [ 706 | { 707 | "name": "stdout", 708 | "output_type": "stream", 709 | "text": [ 710 | "200\n" 711 | ] 712 | } 713 | ], 714 | "source": [ 715 | "result = area(10, 20)\n", 716 | "print(result)" 717 | ] 718 | }, 719 | { 720 | "cell_type": "markdown", 721 | "metadata": {}, 722 | "source": [ 723 | "We can create even more helpful and complex functions by using what knowledge we have gained till now. \n", 724 | "This is the perfect time for you to take a step back and think about one thing that you can write a function for.\n", 725 | "\n", 726 | "Here is an example to get you started. It converts seconds to hours, minutes, and seconds." 727 | ] 728 | }, 729 | { 730 | "cell_type": "code", 731 | "execution_count": 157, 732 | "metadata": {}, 733 | "outputs": [], 734 | "source": [ 735 | "def convert_seconds(seconds):\n", 736 | " hours = seconds // 3600\n", 737 | " minutes = (seconds - hours * 3600) // 60\n", 738 | " remaining_seconds = seconds - hours * 3600 - minutes * 60\n", 739 | " return hours, minutes, remaining_seconds" 740 | ] 741 | }, 742 | { 743 | "cell_type": "code", 744 | "execution_count": 158, 745 | "metadata": {}, 746 | "outputs": [ 747 | { 748 | "name": "stdout", 749 | "output_type": "stream", 750 | "text": [ 751 | "1 0 0\n" 752 | ] 753 | } 754 | ], 755 | "source": [ 756 | "h, m, s = convert_seconds(3600)\n", 757 | "print(h, m, s)" 758 | ] 759 | }, 760 | { 761 | "cell_type": "markdown", 762 | "metadata": {}, 763 | "source": [ 764 | "### Comparators\n", 765 | "\n", 766 | "In python we use what are called comparators to compare data. \n", 767 | "The following comparators are generally used in python:\n", 768 | "- \\> to check if the left hand side is **greater than** the right hand side\n", 769 | "- \\< to check if the left hand side is **lesser than** the right hand side\n", 770 | "- \\>= to check if the left hand side is **greater than or equal** to the right hand side\n", 771 | "- \\<= to check if the left hand side is **lesser than or equal** to the right hand side\n", 772 | "- == to check if the left hand side is **equal** to the right hand side\n", 773 | "- != to check if the left hand side is **not equal** to the right hand side\n", 774 | "\n", 775 | "The comparators return a boolean value (True/False) indicating if the expression is valid or not." 776 | ] 777 | }, 778 | { 779 | "cell_type": "code", 780 | "execution_count": 159, 781 | "metadata": {}, 782 | "outputs": [ 783 | { 784 | "name": "stdout", 785 | "output_type": "stream", 786 | "text": [ 787 | "False\n" 788 | ] 789 | } 790 | ], 791 | "source": [ 792 | "print(18 < 10)" 793 | ] 794 | }, 795 | { 796 | "cell_type": "code", 797 | "execution_count": 160, 798 | "metadata": {}, 799 | "outputs": [ 800 | { 801 | "name": "stdout", 802 | "output_type": "stream", 803 | "text": [ 804 | "True\n" 805 | ] 806 | } 807 | ], 808 | "source": [ 809 | "print(10 > 1)" 810 | ] 811 | }, 812 | { 813 | "cell_type": "code", 814 | "execution_count": 161, 815 | "metadata": {}, 816 | "outputs": [ 817 | { 818 | "name": "stdout", 819 | "output_type": "stream", 820 | "text": [ 821 | "True\n" 822 | ] 823 | } 824 | ], 825 | "source": [ 826 | "print((10/2) == 5)" 827 | ] 828 | }, 829 | { 830 | "cell_type": "code", 831 | "execution_count": 162, 832 | "metadata": {}, 833 | "outputs": [ 834 | { 835 | "name": "stdout", 836 | "output_type": "stream", 837 | "text": [ 838 | "True\n" 839 | ] 840 | } 841 | ], 842 | "source": [ 843 | "print(1 != 2)" 844 | ] 845 | }, 846 | { 847 | "cell_type": "code", 848 | "execution_count": 163, 849 | "metadata": {}, 850 | "outputs": [ 851 | { 852 | "name": "stdout", 853 | "output_type": "stream", 854 | "text": [ 855 | "True\n" 856 | ] 857 | } 858 | ], 859 | "source": [ 860 | "print(1.0 <= 1.1)" 861 | ] 862 | }, 863 | { 864 | "cell_type": "code", 865 | "execution_count": 164, 866 | "metadata": {}, 867 | "outputs": [ 868 | { 869 | "name": "stdout", 870 | "output_type": "stream", 871 | "text": [ 872 | "False\n" 873 | ] 874 | } 875 | ], 876 | "source": [ 877 | "print(2.0 >= 3.0)" 878 | ] 879 | }, 880 | { 881 | "cell_type": "markdown", 882 | "metadata": {}, 883 | "source": [ 884 | "The above examples were quite simple and basically used numbers (integers or floats). \n", 885 | "We can also use some comparators with strings to check if they are greater than or less than other strings. In the context of strings, a string is said to be less than another one if it comes first in the dictionary and vice versa." 886 | ] 887 | }, 888 | { 889 | "cell_type": "code", 890 | "execution_count": 165, 891 | "metadata": {}, 892 | "outputs": [ 893 | { 894 | "name": "stdout", 895 | "output_type": "stream", 896 | "text": [ 897 | "True\n" 898 | ] 899 | } 900 | ], 901 | "source": [ 902 | "print(\"AA\" < \"AB\")" 903 | ] 904 | }, 905 | { 906 | "cell_type": "code", 907 | "execution_count": 166, 908 | "metadata": { 909 | "scrolled": true 910 | }, 911 | "outputs": [ 912 | { 913 | "name": "stdout", 914 | "output_type": "stream", 915 | "text": [ 916 | "False\n" 917 | ] 918 | } 919 | ], 920 | "source": [ 921 | "print(\"bz\" > \"za\")" 922 | ] 923 | }, 924 | { 925 | "cell_type": "markdown", 926 | "metadata": {}, 927 | "source": [ 928 | "We can't use the less than and greater than comparators between strings and numbers." 929 | ] 930 | }, 931 | { 932 | "cell_type": "code", 933 | "execution_count": 167, 934 | "metadata": {}, 935 | "outputs": [ 936 | { 937 | "ename": "TypeError", 938 | "evalue": "'<' not supported between instances of 'int' and 'str'", 939 | "output_type": "error", 940 | "traceback": [ 941 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 942 | "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", 943 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m \u001b[1;33m<\u001b[0m \u001b[1;34m\"10\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 944 | "\u001b[1;31mTypeError\u001b[0m: '<' not supported between instances of 'int' and 'str'" 945 | ] 946 | } 947 | ], 948 | "source": [ 949 | "print(1 < \"10\")" 950 | ] 951 | }, 952 | { 953 | "cell_type": "code", 954 | "execution_count": 168, 955 | "metadata": {}, 956 | "outputs": [ 957 | { 958 | "ename": "TypeError", 959 | "evalue": "'>' not supported between instances of 'str' and 'int'", 960 | "output_type": "error", 961 | "traceback": [ 962 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 963 | "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", 964 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"10\"\u001b[0m \u001b[1;33m>\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 965 | "\u001b[1;31mTypeError\u001b[0m: '>' not supported between instances of 'str' and 'int'" 966 | ] 967 | } 968 | ], 969 | "source": [ 970 | "print(\"10\" > 1)" 971 | ] 972 | }, 973 | { 974 | "cell_type": "markdown", 975 | "metadata": {}, 976 | "source": [ 977 | "We can also use the equal and not equal comparators between two strings, and a string and number. The latter case will always return False as a string can never be equal to a number data type in python." 978 | ] 979 | }, 980 | { 981 | "cell_type": "code", 982 | "execution_count": 169, 983 | "metadata": {}, 984 | "outputs": [ 985 | { 986 | "name": "stdout", 987 | "output_type": "stream", 988 | "text": [ 989 | "True\n" 990 | ] 991 | } 992 | ], 993 | "source": [ 994 | "print(\"cat\" == \"cat\")" 995 | ] 996 | }, 997 | { 998 | "cell_type": "code", 999 | "execution_count": 170, 1000 | "metadata": {}, 1001 | "outputs": [ 1002 | { 1003 | "name": "stdout", 1004 | "output_type": "stream", 1005 | "text": [ 1006 | "True\n" 1007 | ] 1008 | } 1009 | ], 1010 | "source": [ 1011 | "print(\"cat\" != \"dog\")" 1012 | ] 1013 | }, 1014 | { 1015 | "cell_type": "code", 1016 | "execution_count": 171, 1017 | "metadata": {}, 1018 | "outputs": [ 1019 | { 1020 | "name": "stdout", 1021 | "output_type": "stream", 1022 | "text": [ 1023 | "False\n" 1024 | ] 1025 | } 1026 | ], 1027 | "source": [ 1028 | "print(1 == \"1\")" 1029 | ] 1030 | }, 1031 | { 1032 | "cell_type": "markdown", 1033 | "metadata": {}, 1034 | "source": [ 1035 | "### Logical operators\n", 1036 | "\n", 1037 | "We can use logical operators to combine simple expressions into complex expressions. \n", 1038 | "There are three basic logical operators:\n", 1039 | "- and = returns true if both the expressions are valid\n", 1040 | "- or = returns true if at least one expression is valid\n", 1041 | "- not = returns true if the expression is invalid and false if it is valid" 1042 | ] 1043 | }, 1044 | { 1045 | "cell_type": "code", 1046 | "execution_count": 172, 1047 | "metadata": {}, 1048 | "outputs": [ 1049 | { 1050 | "name": "stdout", 1051 | "output_type": "stream", 1052 | "text": [ 1053 | "False\n" 1054 | ] 1055 | } 1056 | ], 1057 | "source": [ 1058 | "print(1 == 10 and 2 != 3)" 1059 | ] 1060 | }, 1061 | { 1062 | "cell_type": "code", 1063 | "execution_count": 173, 1064 | "metadata": {}, 1065 | "outputs": [ 1066 | { 1067 | "name": "stdout", 1068 | "output_type": "stream", 1069 | "text": [ 1070 | "True\n" 1071 | ] 1072 | } 1073 | ], 1074 | "source": [ 1075 | "print(1 == 10 or 2 != 3)" 1076 | ] 1077 | }, 1078 | { 1079 | "cell_type": "code", 1080 | "execution_count": 174, 1081 | "metadata": {}, 1082 | "outputs": [ 1083 | { 1084 | "name": "stdout", 1085 | "output_type": "stream", 1086 | "text": [ 1087 | "False\n" 1088 | ] 1089 | } 1090 | ], 1091 | "source": [ 1092 | "print(not 42 == 42)" 1093 | ] 1094 | }, 1095 | { 1096 | "cell_type": "markdown", 1097 | "metadata": {}, 1098 | "source": [ 1099 | "### Branching with IF statements\n", 1100 | "\n", 1101 | "Now that we know about comparators and booleans, we can construct something called branches. \n", 1102 | "A branch in a program is basically a point where we can evaluate a certain condition and proceed based on how the condition evaluates.\n", 1103 | "\n", 1104 | "We use \"if\" statements in python to create branches. \n", 1105 | "These work like they do in real life. \n", 1106 | "``` \n", 1107 | "if condition is true:\n", 1108 | " do something\n", 1109 | "```\n", 1110 | "That is also basically how we define an if statement. The following example will make things clear. \n", 1111 | "\n", 1112 | "Suppose we want to **create a function that takes in a username as input and returns a string indicating if the username is valid or invalid**.\n", 1113 | "\n", 1114 | "We declare a username to be invalid if it is shorter than 3 letters. \n", 1115 | "We can use the built-in `len()` function to get the length of a string." 1116 | ] 1117 | }, 1118 | { 1119 | "cell_type": "code", 1120 | "execution_count": 175, 1121 | "metadata": {}, 1122 | "outputs": [], 1123 | "source": [ 1124 | "def valid_username(username):\n", 1125 | " if len(username) < 3:\n", 1126 | " return \"The username should be longer than 3 letters!\"" 1127 | ] 1128 | }, 1129 | { 1130 | "cell_type": "code", 1131 | "execution_count": 176, 1132 | "metadata": {}, 1133 | "outputs": [ 1134 | { 1135 | "name": "stdout", 1136 | "output_type": "stream", 1137 | "text": [ 1138 | "The username should be longer than 3 letters!\n" 1139 | ] 1140 | } 1141 | ], 1142 | "source": [ 1143 | "print(valid_username(\"ok\"))" 1144 | ] 1145 | }, 1146 | { 1147 | "cell_type": "code", 1148 | "execution_count": 177, 1149 | "metadata": {}, 1150 | "outputs": [ 1151 | { 1152 | "name": "stdout", 1153 | "output_type": "stream", 1154 | "text": [ 1155 | "None\n" 1156 | ] 1157 | } 1158 | ], 1159 | "source": [ 1160 | "print(valid_username(\"good\"))" 1161 | ] 1162 | }, 1163 | { 1164 | "cell_type": "code", 1165 | "execution_count": 178, 1166 | "metadata": {}, 1167 | "outputs": [ 1168 | { 1169 | "name": "stdout", 1170 | "output_type": "stream", 1171 | "text": [ 1172 | "None\n" 1173 | ] 1174 | } 1175 | ], 1176 | "source": [ 1177 | "print(valid_username(\"terminator\"))" 1178 | ] 1179 | }, 1180 | { 1181 | "cell_type": "markdown", 1182 | "metadata": {}, 1183 | "source": [ 1184 | "Here you should note that, since our if statement doesn't execute in the last two cases, the return statement is not reached. Thus the function returns the `None` value indicating that there was nothing to return. \n", 1185 | "That is a weird behaviour. Getting `None` when you type in a valid username doesn't seem so good. \n", 1186 | "\n", 1187 | "What can we do about it? \n", 1188 | "We can extend our `if` statement with an `else` block. The else block executes only when the `if` condition is declared as `False`." 1189 | ] 1190 | }, 1191 | { 1192 | "cell_type": "code", 1193 | "execution_count": 179, 1194 | "metadata": {}, 1195 | "outputs": [], 1196 | "source": [ 1197 | "def valid_username(username):\n", 1198 | " if len(username) < 3:\n", 1199 | " return \"The username should be longer than 3 letters!\"\n", 1200 | " else:\n", 1201 | " return \"Valid username\"" 1202 | ] 1203 | }, 1204 | { 1205 | "cell_type": "code", 1206 | "execution_count": 180, 1207 | "metadata": {}, 1208 | "outputs": [ 1209 | { 1210 | "name": "stdout", 1211 | "output_type": "stream", 1212 | "text": [ 1213 | "The username should be longer than 3 letters!\n" 1214 | ] 1215 | } 1216 | ], 1217 | "source": [ 1218 | "print(valid_username(\"ok\"))" 1219 | ] 1220 | }, 1221 | { 1222 | "cell_type": "code", 1223 | "execution_count": 181, 1224 | "metadata": {}, 1225 | "outputs": [ 1226 | { 1227 | "name": "stdout", 1228 | "output_type": "stream", 1229 | "text": [ 1230 | "Valid username\n" 1231 | ] 1232 | } 1233 | ], 1234 | "source": [ 1235 | "print(valid_username(\"good\"))" 1236 | ] 1237 | }, 1238 | { 1239 | "cell_type": "code", 1240 | "execution_count": 182, 1241 | "metadata": { 1242 | "scrolled": true 1243 | }, 1244 | "outputs": [ 1245 | { 1246 | "name": "stdout", 1247 | "output_type": "stream", 1248 | "text": [ 1249 | "Valid username\n" 1250 | ] 1251 | } 1252 | ], 1253 | "source": [ 1254 | "print(valid_username(\"terminator\"))" 1255 | ] 1256 | }, 1257 | { 1258 | "cell_type": "markdown", 1259 | "metadata": {}, 1260 | "source": [ 1261 | "What if we want to add a new condition. As longer usernames tend to be difficult to store/remember, we want to make sure that all usernames are less than 7 characters long. \n", 1262 | "\n", 1263 | "We can use another `if` statement to write the code as follows." 1264 | ] 1265 | }, 1266 | { 1267 | "cell_type": "code", 1268 | "execution_count": 183, 1269 | "metadata": {}, 1270 | "outputs": [], 1271 | "source": [ 1272 | "def valid_username(username):\n", 1273 | " if len(username) < 3:\n", 1274 | " return \"The username should be longer than 3 letters!\"\n", 1275 | " else:\n", 1276 | " if len(username) > 7:\n", 1277 | " return \"The username should be shorter than 7 letters!\"\n", 1278 | " else:\n", 1279 | " return \"Valid username\"" 1280 | ] 1281 | }, 1282 | { 1283 | "cell_type": "code", 1284 | "execution_count": 184, 1285 | "metadata": {}, 1286 | "outputs": [ 1287 | { 1288 | "name": "stdout", 1289 | "output_type": "stream", 1290 | "text": [ 1291 | "The username should be longer than 3 letters!\n" 1292 | ] 1293 | } 1294 | ], 1295 | "source": [ 1296 | "print(valid_username(\"ok\"))" 1297 | ] 1298 | }, 1299 | { 1300 | "cell_type": "code", 1301 | "execution_count": 185, 1302 | "metadata": {}, 1303 | "outputs": [ 1304 | { 1305 | "name": "stdout", 1306 | "output_type": "stream", 1307 | "text": [ 1308 | "Valid username\n" 1309 | ] 1310 | } 1311 | ], 1312 | "source": [ 1313 | "print(valid_username(\"good\"))" 1314 | ] 1315 | }, 1316 | { 1317 | "cell_type": "code", 1318 | "execution_count": 186, 1319 | "metadata": {}, 1320 | "outputs": [ 1321 | { 1322 | "name": "stdout", 1323 | "output_type": "stream", 1324 | "text": [ 1325 | "The username should be shorter than 7 letters!\n" 1326 | ] 1327 | } 1328 | ], 1329 | "source": [ 1330 | "print(valid_username(\"terminator\"))" 1331 | ] 1332 | }, 1333 | { 1334 | "cell_type": "markdown", 1335 | "metadata": {}, 1336 | "source": [ 1337 | "Adding even more conditions will make the code pretty long and difficult to manage. Shouldn't python have some functionality to prevent this?\n", 1338 | "\n", 1339 | "Indeed it does. We can add something called an `elif` block. The `elif` block checks a condition after the `if` condition evaluates to `False`. " 1340 | ] 1341 | }, 1342 | { 1343 | "cell_type": "code", 1344 | "execution_count": 187, 1345 | "metadata": {}, 1346 | "outputs": [], 1347 | "source": [ 1348 | "def valid_username(username):\n", 1349 | " if len(username) < 3:\n", 1350 | " return \"The username should be longer than 3 letters!\"\n", 1351 | " elif len(username) > 7:\n", 1352 | " return \"The username should be shorter than 7 letters!\"\n", 1353 | " else:\n", 1354 | " return \"Valid username\"" 1355 | ] 1356 | }, 1357 | { 1358 | "cell_type": "code", 1359 | "execution_count": 188, 1360 | "metadata": {}, 1361 | "outputs": [ 1362 | { 1363 | "name": "stdout", 1364 | "output_type": "stream", 1365 | "text": [ 1366 | "The username should be longer than 3 letters!\n" 1367 | ] 1368 | } 1369 | ], 1370 | "source": [ 1371 | "print(valid_username(\"ok\"))" 1372 | ] 1373 | }, 1374 | { 1375 | "cell_type": "code", 1376 | "execution_count": 189, 1377 | "metadata": {}, 1378 | "outputs": [ 1379 | { 1380 | "name": "stdout", 1381 | "output_type": "stream", 1382 | "text": [ 1383 | "Valid username\n" 1384 | ] 1385 | } 1386 | ], 1387 | "source": [ 1388 | "print(valid_username(\"good\"))" 1389 | ] 1390 | }, 1391 | { 1392 | "cell_type": "code", 1393 | "execution_count": 190, 1394 | "metadata": {}, 1395 | "outputs": [ 1396 | { 1397 | "name": "stdout", 1398 | "output_type": "stream", 1399 | "text": [ 1400 | "The username should be shorter than 7 letters!\n" 1401 | ] 1402 | } 1403 | ], 1404 | "source": [ 1405 | "print(valid_username(\"terminator\"))" 1406 | ] 1407 | }, 1408 | { 1409 | "cell_type": "markdown", 1410 | "metadata": {}, 1411 | "source": [ 1412 | "Here is an interesting thing, a return statement always exits the function. Thus, none of the code after a `return` statement will be executed. \n", 1413 | "Thus, we can omit the final `else` block with just a return statement and the function will operate in the same way as before." 1414 | ] 1415 | }, 1416 | { 1417 | "cell_type": "code", 1418 | "execution_count": 191, 1419 | "metadata": {}, 1420 | "outputs": [], 1421 | "source": [ 1422 | "def valid_username(username):\n", 1423 | " if len(username) < 3:\n", 1424 | " return \"The username should be longer than 3 letters!\"\n", 1425 | " elif len(username) > 7:\n", 1426 | " return \"The username should be shorter than 7 letters!\"\n", 1427 | " return \"Valid username\"" 1428 | ] 1429 | }, 1430 | { 1431 | "cell_type": "code", 1432 | "execution_count": 192, 1433 | "metadata": {}, 1434 | "outputs": [ 1435 | { 1436 | "name": "stdout", 1437 | "output_type": "stream", 1438 | "text": [ 1439 | "The username should be longer than 3 letters!\n" 1440 | ] 1441 | } 1442 | ], 1443 | "source": [ 1444 | "print(valid_username(\"ok\"))" 1445 | ] 1446 | }, 1447 | { 1448 | "cell_type": "code", 1449 | "execution_count": 193, 1450 | "metadata": {}, 1451 | "outputs": [ 1452 | { 1453 | "name": "stdout", 1454 | "output_type": "stream", 1455 | "text": [ 1456 | "Valid username\n" 1457 | ] 1458 | } 1459 | ], 1460 | "source": [ 1461 | "print(valid_username(\"good\"))" 1462 | ] 1463 | }, 1464 | { 1465 | "cell_type": "code", 1466 | "execution_count": 194, 1467 | "metadata": {}, 1468 | "outputs": [ 1469 | { 1470 | "name": "stdout", 1471 | "output_type": "stream", 1472 | "text": [ 1473 | "The username should be shorter than 7 letters!\n" 1474 | ] 1475 | } 1476 | ], 1477 | "source": [ 1478 | "print(valid_username(\"terminator\"))" 1479 | ] 1480 | }, 1481 | { 1482 | "cell_type": "markdown", 1483 | "metadata": {}, 1484 | "source": [ 1485 | "## A note on code style\n", 1486 | "\n", 1487 | "Now that we have the syntax and basics of python out of the way. There is an important point to be discussed. \n", 1488 | "The style in which you write code will be defined by many things, but if you are starting out (which I assume as you are here), there are a few things that you can keep in mind to make things easier in the long run." 1489 | ] 1490 | }, 1491 | { 1492 | "cell_type": "markdown", 1493 | "metadata": {}, 1494 | "source": [ 1495 | "First and foremost, any code you write should be self-documenting (and self-explanatory). \n", 1496 | "Code is not only meant to be executed, but also be understandable and mainly readable. \n", 1497 | "Any code that you write will in future be worked upon by someone else or at least by you and you may have well forgotten what you were initially thinking when you wrote the piece of code.\n", 1498 | "\n", 1499 | "For instance, take a look at the two functions written below. Which one do you think is easier to understand on the first glance?" 1500 | ] 1501 | }, 1502 | { 1503 | "cell_type": "code", 1504 | "execution_count": 195, 1505 | "metadata": {}, 1506 | "outputs": [ 1507 | { 1508 | "name": "stdout", 1509 | "output_type": "stream", 1510 | "text": [ 1511 | "19.625\n" 1512 | ] 1513 | } 1514 | ], 1515 | "source": [ 1516 | "def calculate(r):\n", 1517 | " q = 3.14\n", 1518 | " z = q * ((r/2.0)** 2)\n", 1519 | " print(z)\n", 1520 | " \n", 1521 | "calculate(5)" 1522 | ] 1523 | }, 1524 | { 1525 | "cell_type": "code", 1526 | "execution_count": 196, 1527 | "metadata": {}, 1528 | "outputs": [ 1529 | { 1530 | "name": "stdout", 1531 | "output_type": "stream", 1532 | "text": [ 1533 | "19.625\n" 1534 | ] 1535 | } 1536 | ], 1537 | "source": [ 1538 | "def circle_area(diameter):\n", 1539 | " pi = 3.14\n", 1540 | " radius = diameter/2.0\n", 1541 | " area = pi * (radius ** 2)\n", 1542 | " print(area)\n", 1543 | "\n", 1544 | "circle_area(5)" 1545 | ] 1546 | }, 1547 | { 1548 | "cell_type": "markdown", 1549 | "metadata": {}, 1550 | "source": [ 1551 | "Here are some tips to write code that is easily understandable and readable for everyone:\n", 1552 | "- choose proper variable names that are related to the function they carry out\n", 1553 | "- name your functions properly\n", 1554 | "- refrain from writing complex pieces of code or equations until and unless it is necessary" 1555 | ] 1556 | }, 1557 | { 1558 | "cell_type": "markdown", 1559 | "metadata": {}, 1560 | "source": [ 1561 | "One final thing that you can do to help readers/developers understand you code is provide comments. \n", 1562 | "Comments in python are indicated by a hash (#) \n", 1563 | "Any line followed by a # is not executed by the python interpreter and is only present as a reference for the humans reading the code.\n", 1564 | "\n", 1565 | "For example:" 1566 | ] 1567 | }, 1568 | { 1569 | "cell_type": "code", 1570 | "execution_count": 197, 1571 | "metadata": {}, 1572 | "outputs": [ 1573 | { 1574 | "name": "stdout", 1575 | "output_type": "stream", 1576 | "text": [ 1577 | "78.5\n" 1578 | ] 1579 | } 1580 | ], 1581 | "source": [ 1582 | "# A function to calculate the area of a circle using its radius\n", 1583 | "def circle_area(radius):\n", 1584 | " pi = 3.14\n", 1585 | " area = pi * (radius ** 2)\n", 1586 | " print(area)\n", 1587 | "\n", 1588 | "circle_area(5)" 1589 | ] 1590 | } 1591 | ], 1592 | "metadata": { 1593 | "kernelspec": { 1594 | "display_name": "Python 3", 1595 | "language": "python", 1596 | "name": "python3" 1597 | }, 1598 | "language_info": { 1599 | "codemirror_mode": { 1600 | "name": "ipython", 1601 | "version": 3 1602 | }, 1603 | "file_extension": ".py", 1604 | "mimetype": "text/x-python", 1605 | "name": "python", 1606 | "nbconvert_exporter": "python", 1607 | "pygments_lexer": "ipython3", 1608 | "version": "3.8.3" 1609 | } 1610 | }, 1611 | "nbformat": 4, 1612 | "nbformat_minor": 4 1613 | } 1614 | -------------------------------------------------------------------------------- /Python-Notebooks/2.Loops and Recursions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Loops and Recursions\n", 8 | "\n", 9 | "**By Arpit Omprakash, Byte Sized Code**" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "## Loops" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "### While Loops\n", 24 | "\n", 25 | "While loops are blocks of code that run till a certain condition evaluates to be true. \n", 26 | "They are more or less defined in the same way as `if` statements. \n", 27 | "\n", 28 | "```\n", 29 | "while condition_evaluates_to_true:\n", 30 | " do_something\n", 31 | "```" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 1, 37 | "metadata": {}, 38 | "outputs": [ 39 | { 40 | "name": "stdout", 41 | "output_type": "stream", 42 | "text": [ 43 | "Not there yet, x= 0\n", 44 | "Not there yet, x= 1\n", 45 | "Not there yet, x= 2\n", 46 | "Not there yet, x= 3\n", 47 | "Not there yet, x= 4\n" 48 | ] 49 | } 50 | ], 51 | "source": [ 52 | "x = 0\n", 53 | "while x < 5:\n", 54 | " print(\"Not there yet, x= \" + str(x))\n", 55 | " x = x + 1" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "We can shorten the assignment statement by using other **assignment** operators that python provides. \n", 63 | "**Assignment Operators**\n", 64 | "- x += 1 is the same as x = x + 1\n", 65 | "- x \\*= 10 is the same as x = x * 10 \n", 66 | "... \n", 67 | "\n", 68 | "You get the idea" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": 2, 74 | "metadata": {}, 75 | "outputs": [ 76 | { 77 | "name": "stdout", 78 | "output_type": "stream", 79 | "text": [ 80 | "Attempt 1\n", 81 | "Attempt 2\n", 82 | "Attempt 3\n", 83 | "Attempt 4\n", 84 | "Attempt 5\n", 85 | "Done\n" 86 | ] 87 | } 88 | ], 89 | "source": [ 90 | "def attempts(n):\n", 91 | " x = 1\n", 92 | " while x <= n:\n", 93 | " print(\"Attempt \" + str(x))\n", 94 | " x += 1\n", 95 | " print(\"Done\")\n", 96 | "\n", 97 | "attempts(5)" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "While loops are traditionally used in cases where a certain condition is required to be met before proceeding. For example:" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": 3, 110 | "metadata": {}, 111 | "outputs": [ 112 | { 113 | "name": "stdout", 114 | "output_type": "stream", 115 | "text": [ 116 | "Enter your name: omprakash\n", 117 | "Enter your name: elvis\n", 118 | "Enter your name: matt\n", 119 | "Enter your name: arpit\n", 120 | "Name = arpit\n" 121 | ] 122 | } 123 | ], 124 | "source": [ 125 | "name = \"\"\n", 126 | "while name != \"arpit\":\n", 127 | " name = input(\"Enter your name: \")\n", 128 | "print(\"Name = \" + name )" 129 | ] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "metadata": {}, 134 | "source": [ 135 | "**Common Errors while writing While Loops**" 136 | ] 137 | }, 138 | { 139 | "cell_type": "markdown", 140 | "metadata": {}, 141 | "source": [ 142 | "- Forgetting to initialize the variable" 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "execution_count": 4, 148 | "metadata": {}, 149 | "outputs": [ 150 | { 151 | "ename": "NameError", 152 | "evalue": "name 'my_var' is not defined", 153 | "output_type": "error", 154 | "traceback": [ 155 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 156 | "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", 157 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mwhile\u001b[0m \u001b[0mmy_var\u001b[0m \u001b[1;33m<\u001b[0m \u001b[1;36m5\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmy_var\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[0mmy_var\u001b[0m \u001b[1;33m+=\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 158 | "\u001b[1;31mNameError\u001b[0m: name 'my_var' is not defined" 159 | ] 160 | } 161 | ], 162 | "source": [ 163 | "while my_var < 5:\n", 164 | " print(my_var)\n", 165 | " my_var += 1" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": 5, 171 | "metadata": {}, 172 | "outputs": [ 173 | { 174 | "name": "stdout", 175 | "output_type": "stream", 176 | "text": [ 177 | "45 1\n" 178 | ] 179 | } 180 | ], 181 | "source": [ 182 | "x = 1\n", 183 | "_sum = 0\n", 184 | "while x < 10:\n", 185 | " _sum += x\n", 186 | " x += 1\n", 187 | "\n", 188 | "product = 1\n", 189 | "while x < 10:\n", 190 | " product *= x\n", 191 | " x += 1\n", 192 | "\n", 193 | "print(_sum, product)" 194 | ] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "metadata": {}, 199 | "source": [ 200 | "In the second case, we forgot to initialize the value of x before the second while loop. Thus, the second while loop is never executed. The second error may be difficult to catch as python doesn't give us an error." 201 | ] 202 | }, 203 | { 204 | "cell_type": "markdown", 205 | "metadata": {}, 206 | "source": [ 207 | "- Infinite Loops\n", 208 | "\n", 209 | "Infinite loops are the most dreaded problem that one can encounter with a loop. \n", 210 | "They generally happen when you forget to track your variable and the condition in the `while` loop never evaluates to be false. Thus, the loop continues forever." 211 | ] 212 | }, 213 | { 214 | "cell_type": "code", 215 | "execution_count": null, 216 | "metadata": {}, 217 | "outputs": [], 218 | "source": [ 219 | "x = 0\n", 220 | "while x < 10:\n", 221 | " print(\"ok\")\n", 222 | " x -= 1" 223 | ] 224 | }, 225 | { 226 | "cell_type": "code", 227 | "execution_count": null, 228 | "metadata": {}, 229 | "outputs": [], 230 | "source": [ 231 | "x = 1\n", 232 | "while x < 5:\n", 233 | " print(x)" 234 | ] 235 | }, 236 | { 237 | "cell_type": "markdown", 238 | "metadata": {}, 239 | "source": [ 240 | "However sometimes infinite loops are desirable. \n", 241 | "For example, if you have ever used the `ping` command in Linux or `ping -t` command in Windows, you might have noticed that the tool runs till it is stopped manually by the user.\n", 242 | "\n", 243 | "Even in those cases we need to break the loop at some time:\n", 244 | "\n", 245 | "```\n", 246 | "while True:\n", 247 | " do_something_cool()\n", 248 | " if user_requested_to_stop():\n", 249 | " break\n", 250 | "```\n", 251 | "A **break** statement is used to exit an infinite loop when a certain condition is met. \n", 252 | "The break statement can also be used to exit a loop early if the code has achieved its objective." 253 | ] 254 | }, 255 | { 256 | "cell_type": "code", 257 | "execution_count": 8, 258 | "metadata": {}, 259 | "outputs": [ 260 | { 261 | "name": "stdout", 262 | "output_type": "stream", 263 | "text": [ 264 | "0\n", 265 | "1\n", 266 | "2\n" 267 | ] 268 | } 269 | ], 270 | "source": [ 271 | "x = 0\n", 272 | "while x < 5:\n", 273 | " if x == 3:\n", 274 | " break\n", 275 | " print(x)\n", 276 | " x += 1" 277 | ] 278 | }, 279 | { 280 | "cell_type": "markdown", 281 | "metadata": {}, 282 | "source": [ 283 | "### For Loops\n", 284 | "\n", 285 | "For loops are used to iterate over a given sequence of values. \n", 286 | "The syntax is as follows:\n", 287 | "```\n", 288 | "for item in iterable:\n", 289 | " do_something_with_item\n", 290 | "```" 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "execution_count": 9, 296 | "metadata": {}, 297 | "outputs": [ 298 | { 299 | "name": "stdout", 300 | "output_type": "stream", 301 | "text": [ 302 | "0\n", 303 | "1\n", 304 | "2\n", 305 | "3\n", 306 | "4\n" 307 | ] 308 | } 309 | ], 310 | "source": [ 311 | "for x in range(5):\n", 312 | " print(x)" 313 | ] 314 | }, 315 | { 316 | "cell_type": "markdown", 317 | "metadata": {}, 318 | "source": [ 319 | "The range function returns an iterable sequence of numbers. \n", 320 | "- `range(n)` generates values from `0` to `n-1`\n", 321 | "- `range(m, n)` generates values from `m` to `n-1`\n", 322 | "- `range(m, n, p)` generates values from `m` to `n-1` in steps of `p`" 323 | ] 324 | }, 325 | { 326 | "cell_type": "code", 327 | "execution_count": 10, 328 | "metadata": {}, 329 | "outputs": [ 330 | { 331 | "name": "stdout", 332 | "output_type": "stream", 333 | "text": [ 334 | "5\n", 335 | "6\n", 336 | "7\n", 337 | "8\n", 338 | "9\n" 339 | ] 340 | } 341 | ], 342 | "source": [ 343 | "for i in range(5, 10):\n", 344 | " print(i)" 345 | ] 346 | }, 347 | { 348 | "cell_type": "code", 349 | "execution_count": 11, 350 | "metadata": {}, 351 | "outputs": [ 352 | { 353 | "name": "stdout", 354 | "output_type": "stream", 355 | "text": [ 356 | "5\n", 357 | "7\n", 358 | "9\n" 359 | ] 360 | } 361 | ], 362 | "source": [ 363 | "for i in range(5, 10, 2):\n", 364 | " print(i)" 365 | ] 366 | }, 367 | { 368 | "cell_type": "markdown", 369 | "metadata": {}, 370 | "source": [ 371 | "You might be wondering why do we have a separate kind of loop, we can write the previous loops even as `while` loops. \n", 372 | "The answer lies in the power of `for` loops to work with any iterable item, including lists, dictionaries, and strings." 373 | ] 374 | }, 375 | { 376 | "cell_type": "code", 377 | "execution_count": 12, 378 | "metadata": {}, 379 | "outputs": [ 380 | { 381 | "name": "stdout", 382 | "output_type": "stream", 383 | "text": [ 384 | "How you doing Chandler?\n", 385 | "How you doing Monica?\n", 386 | "How you doing Ross?\n", 387 | "How you doing Rachel?\n", 388 | "How you doing Phoebe?\n", 389 | "How you doing Joey?\n" 390 | ] 391 | } 392 | ], 393 | "source": [ 394 | "friends = [\"Chandler\", \"Monica\", \"Ross\", \"Rachel\", \"Phoebe\", \"Joey\"]\n", 395 | "for friend in friends:\n", 396 | " print(\"How you doing \" + friend + \"?\")" 397 | ] 398 | }, 399 | { 400 | "cell_type": "code", 401 | "execution_count": 13, 402 | "metadata": {}, 403 | "outputs": [ 404 | { 405 | "name": "stdout", 406 | "output_type": "stream", 407 | "text": [ 408 | "0 -17.77777777777778\n", 409 | "10 -12.222222222222221\n", 410 | "20 -6.666666666666667\n", 411 | "30 -1.1111111111111112\n", 412 | "40 4.444444444444445\n", 413 | "50 10.0\n", 414 | "60 15.555555555555555\n", 415 | "70 21.11111111111111\n", 416 | "80 26.666666666666668\n", 417 | "90 32.22222222222222\n", 418 | "100 37.77777777777778\n" 419 | ] 420 | } 421 | ], 422 | "source": [ 423 | "def to_celsius(x):\n", 424 | " return (x - 32) * 5 / 9\n", 425 | "\n", 426 | "for x in range(0, 101, 10):\n", 427 | " print(x, to_celsius(x))" 428 | ] 429 | }, 430 | { 431 | "cell_type": "markdown", 432 | "metadata": {}, 433 | "source": [ 434 | "**Nested For Loops**\n", 435 | "\n", 436 | "We can use nested for loops to iterate over two iterable items simultaneously and perform some function with both of them. \n", 437 | "Here's an example:" 438 | ] 439 | }, 440 | { 441 | "cell_type": "code", 442 | "execution_count": 14, 443 | "metadata": {}, 444 | "outputs": [ 445 | { 446 | "name": "stdout", 447 | "output_type": "stream", 448 | "text": [ 449 | "big apple\n", 450 | "big cherry\n", 451 | "big orange\n", 452 | "tasty apple\n", 453 | "tasty cherry\n", 454 | "tasty orange\n", 455 | "fresh apple\n", 456 | "fresh cherry\n", 457 | "fresh orange\n" 458 | ] 459 | } 460 | ], 461 | "source": [ 462 | "adj = [\"big\", \"tasty\", \"fresh\"]\n", 463 | "fruits = [\"apple\", \"cherry\", \"orange\"]\n", 464 | "\n", 465 | "for adjective in adj:\n", 466 | " for fruit in fruits:\n", 467 | " print(adjective + \" \" + fruit)" 468 | ] 469 | }, 470 | { 471 | "cell_type": "markdown", 472 | "metadata": {}, 473 | "source": [ 474 | "**Common Errors when writing For Loops**" 475 | ] 476 | }, 477 | { 478 | "cell_type": "markdown", 479 | "metadata": {}, 480 | "source": [ 481 | "- Trying to iterate over something that is not iterable \n", 482 | "\n", 483 | "This is a frequent error for beginners as they often confuse data types." 484 | ] 485 | }, 486 | { 487 | "cell_type": "code", 488 | "execution_count": 15, 489 | "metadata": {}, 490 | "outputs": [ 491 | { 492 | "ename": "TypeError", 493 | "evalue": "'int' object is not iterable", 494 | "output_type": "error", 495 | "traceback": [ 496 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 497 | "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", 498 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;36m25\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 499 | "\u001b[1;31mTypeError\u001b[0m: 'int' object is not iterable" 500 | ] 501 | } 502 | ], 503 | "source": [ 504 | "for x in 25:\n", 505 | " print(x)" 506 | ] 507 | }, 508 | { 509 | "cell_type": "markdown", 510 | "metadata": {}, 511 | "source": [ 512 | "- Iterating over the wrong data type\n", 513 | "\n", 514 | "Lets again greet our friends" 515 | ] 516 | }, 517 | { 518 | "cell_type": "code", 519 | "execution_count": 16, 520 | "metadata": {}, 521 | "outputs": [], 522 | "source": [ 523 | "def greet_friends(friends):\n", 524 | " for friend in friends:\n", 525 | " print(\"Hi \" + friend)" 526 | ] 527 | }, 528 | { 529 | "cell_type": "code", 530 | "execution_count": 17, 531 | "metadata": {}, 532 | "outputs": [ 533 | { 534 | "name": "stdout", 535 | "output_type": "stream", 536 | "text": [ 537 | "Hi Chandler\n", 538 | "Hi Monica\n", 539 | "Hi Ross\n", 540 | "Hi Rachel\n", 541 | "Hi Phoebe\n", 542 | "Hi Joey\n" 543 | ] 544 | } 545 | ], 546 | "source": [ 547 | "greet_friends(friends)" 548 | ] 549 | }, 550 | { 551 | "cell_type": "markdown", 552 | "metadata": {}, 553 | "source": [ 554 | "What if we just want to say hi to chandler? \n", 555 | "Lets try putting his name in the function." 556 | ] 557 | }, 558 | { 559 | "cell_type": "code", 560 | "execution_count": 18, 561 | "metadata": {}, 562 | "outputs": [ 563 | { 564 | "name": "stdout", 565 | "output_type": "stream", 566 | "text": [ 567 | "Hi c\n", 568 | "Hi h\n", 569 | "Hi a\n", 570 | "Hi n\n", 571 | "Hi d\n", 572 | "Hi l\n", 573 | "Hi e\n", 574 | "Hi r\n" 575 | ] 576 | } 577 | ], 578 | "source": [ 579 | "greet_friends(\"chandler\")" 580 | ] 581 | }, 582 | { 583 | "cell_type": "markdown", 584 | "metadata": {}, 585 | "source": [ 586 | "What's the problem here? \n", 587 | "The for loop here iterates over the string that we supplied, thus, we have to enclose the single string in a list before presenting it to the function." 588 | ] 589 | }, 590 | { 591 | "cell_type": "code", 592 | "execution_count": 19, 593 | "metadata": {}, 594 | "outputs": [ 595 | { 596 | "name": "stdout", 597 | "output_type": "stream", 598 | "text": [ 599 | "Hi chandler\n" 600 | ] 601 | } 602 | ], 603 | "source": [ 604 | "greet_friends([\"chandler\"])" 605 | ] 606 | }, 607 | { 608 | "cell_type": "markdown", 609 | "metadata": {}, 610 | "source": [ 611 | "## Recursion\n", 612 | "\n", 613 | "The repeated application of the same procedure to a smaller problem. \n", 614 | "It lets us tackle complex problems by reducing the problem to a simpler one. \n", 615 | "In programming, recursion is a way of doing a repetitive task by having a function call itself. \n", 616 | "A recursive function calls itself usually with a modified parameter till it reaches a specific condition. This is called the base case.\n", 617 | "\n", 618 | "Lets dive in to the most classic example of recursion." 619 | ] 620 | }, 621 | { 622 | "cell_type": "code", 623 | "execution_count": 20, 624 | "metadata": {}, 625 | "outputs": [], 626 | "source": [ 627 | "def factorial(n):\n", 628 | " # base case\n", 629 | " if n == 1:\n", 630 | " return 1\n", 631 | " # call the same function with a smaller value\n", 632 | " return n * factorial(n-1)" 633 | ] 634 | }, 635 | { 636 | "cell_type": "code", 637 | "execution_count": 21, 638 | "metadata": {}, 639 | "outputs": [ 640 | { 641 | "name": "stdout", 642 | "output_type": "stream", 643 | "text": [ 644 | "3628800\n" 645 | ] 646 | } 647 | ], 648 | "source": [ 649 | "print(factorial(10))" 650 | ] 651 | }, 652 | { 653 | "cell_type": "markdown", 654 | "metadata": {}, 655 | "source": [ 656 | "Lets dissect the function above to understand what's happening under the hood." 657 | ] 658 | }, 659 | { 660 | "cell_type": "code", 661 | "execution_count": 22, 662 | "metadata": {}, 663 | "outputs": [], 664 | "source": [ 665 | "def _factorial(n):\n", 666 | " print(\"Factorial called with \" + str(n))\n", 667 | " if n == 1:\n", 668 | " print(\"Base case evaluated. Returning 1\")\n", 669 | " return 1\n", 670 | " result = n * _factorial(n-1)\n", 671 | " print(\"Returning \" + str(result) + \" for factorial of \" + str(n))\n", 672 | " return result" 673 | ] 674 | }, 675 | { 676 | "cell_type": "code", 677 | "execution_count": 23, 678 | "metadata": {}, 679 | "outputs": [ 680 | { 681 | "name": "stdout", 682 | "output_type": "stream", 683 | "text": [ 684 | "Factorial called with 5\n", 685 | "Factorial called with 4\n", 686 | "Factorial called with 3\n", 687 | "Factorial called with 2\n", 688 | "Factorial called with 1\n", 689 | "Base case evaluated. Returning 1\n", 690 | "Returning 2 for factorial of 2\n", 691 | "Returning 6 for factorial of 3\n", 692 | "Returning 24 for factorial of 4\n", 693 | "Returning 120 for factorial of 5\n", 694 | "120\n" 695 | ] 696 | } 697 | ], 698 | "source": [ 699 | "print(_factorial(5))" 700 | ] 701 | }, 702 | { 703 | "cell_type": "markdown", 704 | "metadata": {}, 705 | "source": [ 706 | "As we can see above, the factorial function repeatedly calls itself with smaller and smaller values till it reaches the base case. \n", 707 | "Once at the base case, the function returns the value 1 \n", 708 | "After that, one by one, all the previous function calls return the value multiplied by the value that the functions were called with." 709 | ] 710 | }, 711 | { 712 | "cell_type": "markdown", 713 | "metadata": {}, 714 | "source": [ 715 | "**Use case for Recursion** \n", 716 | "Apart from math functions that require recursion, one real world example of where we would use recursion is while counting the number of files in a directory. \n", 717 | "\n", 718 | "The base case would be a directory that has no sub-directories and contains only files. \n", 719 | "A directory that contains sub-directories will call the function recursively till a base case is reached and then start evaluating the number of files in a directory working backwards fromt the base case directory." 720 | ] 721 | }, 722 | { 723 | "cell_type": "markdown", 724 | "metadata": {}, 725 | "source": [ 726 | "**NOTE:** In many languages there is an upper limit to the number of calls that you can make to a recursive function. For python, the upper limit is 1000. That's fine for things like counting subdirectories, but it might not be enough for some mathematical functions." 727 | ] 728 | } 729 | ], 730 | "metadata": { 731 | "kernelspec": { 732 | "display_name": "Python 3", 733 | "language": "python", 734 | "name": "python3" 735 | }, 736 | "language_info": { 737 | "codemirror_mode": { 738 | "name": "ipython", 739 | "version": 3 740 | }, 741 | "file_extension": ".py", 742 | "mimetype": "text/x-python", 743 | "name": "python", 744 | "nbconvert_exporter": "python", 745 | "pygments_lexer": "ipython3", 746 | "version": "3.8.3" 747 | } 748 | }, 749 | "nbformat": 4, 750 | "nbformat_minor": 4 751 | } 752 | -------------------------------------------------------------------------------- /Python-Notebooks/4.Regular Expressions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Regular Expressions in Python\n", 8 | "\n", 9 | "**By Arpit Omprakash, Byte Sized Code**" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "## Basic RegExp" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "**What is a Regular Expression?** \n", 24 | "A Regular Expression (a.k.a. regex or regexp) is essentially a search query for text that's expressed by a string pattern. \n", 25 | "When you run a search against a particular piece of text, anything that matches a regular expression pattern you specified, is returned as a result of the search. \n", 26 | "They allow us to search a text for strings matching a specific pattern." 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "**Module** \n", 34 | "First we need to import the `re` module in python that lets us create and deal with regular expression." 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 34, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "import re" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "metadata": {}, 49 | "source": [ 50 | "**Search** \n", 51 | "\n", 52 | "Most of what we do with regex in python can be accomplished by using the `re.search()` function. \n", 53 | "We provide two arguments to the function: \n", 54 | "- A regex pattern\n", 55 | "- A string to match " 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 35, 61 | "metadata": {}, 62 | "outputs": [ 63 | { 64 | "name": "stdout", 65 | "output_type": "stream", 66 | "text": [ 67 | "\n" 68 | ] 69 | } 70 | ], 71 | "source": [ 72 | "result = re.search(r\"zza\", \"pizza\")\n", 73 | "print(result)" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 36, 79 | "metadata": {}, 80 | "outputs": [ 81 | { 82 | "name": "stdout", 83 | "output_type": "stream", 84 | "text": [ 85 | "\n" 86 | ] 87 | } 88 | ], 89 | "source": [ 90 | "result = re.search(r\"zza\", \"youzza\")\n", 91 | "print(result)" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "As we can see above, when there is a match, `re` returns a `re.Match` object. \n", 99 | "It consists of a `span` that lets us know where the match occured in the given string. \n", 100 | "And a `match`, that shows the exact match that was found.\n", 101 | "\n", 102 | "What about when there is no match? \n", 103 | "It returns a None." 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 37, 109 | "metadata": {}, 110 | "outputs": [ 111 | { 112 | "name": "stdout", 113 | "output_type": "stream", 114 | "text": [ 115 | "None\n" 116 | ] 117 | } 118 | ], 119 | "source": [ 120 | "result = re.search(r\"zza\", \"lol\")\n", 121 | "print(result)" 122 | ] 123 | }, 124 | { 125 | "cell_type": "markdown", 126 | "metadata": {}, 127 | "source": [ 128 | "**IGNORECASE**\n", 129 | "\n", 130 | "By default, regex matching is case sensitive. To make the matching case insensitive we can use the `re.IGNORECASE` flag." 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": 38, 136 | "metadata": {}, 137 | "outputs": [ 138 | { 139 | "name": "stdout", 140 | "output_type": "stream", 141 | "text": [ 142 | "None\n" 143 | ] 144 | } 145 | ], 146 | "source": [ 147 | "print(re.search(r\"ping\", \"Ping\"))" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": 39, 153 | "metadata": {}, 154 | "outputs": [ 155 | { 156 | "name": "stdout", 157 | "output_type": "stream", 158 | "text": [ 159 | "\n" 160 | ] 161 | } 162 | ], 163 | "source": [ 164 | "print(re.search(r\"ping\", \"Ping\", re.IGNORECASE))" 165 | ] 166 | }, 167 | { 168 | "cell_type": "markdown", 169 | "metadata": {}, 170 | "source": [ 171 | "**FINDALL**\n", 172 | "\n", 173 | "The `re.search` function, although very handy, will always return the first match in a string. \n", 174 | "What if we want to match all instances of occurence of a given pattern in a string? \n", 175 | "We use the `re.findall` method." 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": 40, 181 | "metadata": {}, 182 | "outputs": [ 183 | { 184 | "name": "stdout", 185 | "output_type": "stream", 186 | "text": [ 187 | "\n" 188 | ] 189 | } 190 | ], 191 | "source": [ 192 | "print(re.search(r\"ding\", \"dingdingdingding\"))" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": 41, 198 | "metadata": {}, 199 | "outputs": [ 200 | { 201 | "name": "stdout", 202 | "output_type": "stream", 203 | "text": [ 204 | "['ding', 'ding', 'ding', 'ding']\n" 205 | ] 206 | } 207 | ], 208 | "source": [ 209 | "print(re.findall(r\"ding\", \"dingdingdingding\"))" 210 | ] 211 | }, 212 | { 213 | "cell_type": "markdown", 214 | "metadata": {}, 215 | "source": [ 216 | "### Special Characters\n", 217 | "\n", 218 | "Next we take a look at some of the special characters that help with pattern matching in regex." 219 | ] 220 | }, 221 | { 222 | "cell_type": "markdown", 223 | "metadata": {}, 224 | "source": [ 225 | "We can use the caret (^) symbol to explicitly state that we want our match to start from the first character of the line. \n", 226 | "Similarly, we use the dollar ($) symbol to state that we want our match to be at the last character of the line." 227 | ] 228 | }, 229 | { 230 | "cell_type": "code", 231 | "execution_count": 42, 232 | "metadata": {}, 233 | "outputs": [ 234 | { 235 | "name": "stdout", 236 | "output_type": "stream", 237 | "text": [ 238 | "\n" 239 | ] 240 | } 241 | ], 242 | "source": [ 243 | "print(re.search(r\"x\", \"axon\"))" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": 43, 249 | "metadata": {}, 250 | "outputs": [ 251 | { 252 | "name": "stdout", 253 | "output_type": "stream", 254 | "text": [ 255 | "None\n" 256 | ] 257 | } 258 | ], 259 | "source": [ 260 | "print(re.search(r\"^x\", \"axon\"))" 261 | ] 262 | }, 263 | { 264 | "cell_type": "code", 265 | "execution_count": 44, 266 | "metadata": {}, 267 | "outputs": [ 268 | { 269 | "name": "stdout", 270 | "output_type": "stream", 271 | "text": [ 272 | "\n" 273 | ] 274 | } 275 | ], 276 | "source": [ 277 | "print(re.search(r\"n\", \"xenon\"))" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": 45, 283 | "metadata": {}, 284 | "outputs": [ 285 | { 286 | "name": "stdout", 287 | "output_type": "stream", 288 | "text": [ 289 | "\n" 290 | ] 291 | } 292 | ], 293 | "source": [ 294 | "print(re.search(r\"n$\", \"xenon\"))" 295 | ] 296 | }, 297 | { 298 | "cell_type": "markdown", 299 | "metadata": {}, 300 | "source": [ 301 | "**Wildcard** \n", 302 | "\n", 303 | "A wildcard (represented by a dot) is a special character that will match any character (alphanumeric, spaces, digits, and symbols) present in the string." 304 | ] 305 | }, 306 | { 307 | "cell_type": "code", 308 | "execution_count": 46, 309 | "metadata": {}, 310 | "outputs": [ 311 | { 312 | "name": "stdout", 313 | "output_type": "stream", 314 | "text": [ 315 | "\n" 316 | ] 317 | } 318 | ], 319 | "source": [ 320 | "print(re.search(r\"p.ng\", \"penguin\"))" 321 | ] 322 | }, 323 | { 324 | "cell_type": "code", 325 | "execution_count": 47, 326 | "metadata": {}, 327 | "outputs": [ 328 | { 329 | "name": "stdout", 330 | "output_type": "stream", 331 | "text": [ 332 | "\n" 333 | ] 334 | } 335 | ], 336 | "source": [ 337 | "print(re.search(r\"p.ng\", \"ping\"))" 338 | ] 339 | }, 340 | { 341 | "cell_type": "code", 342 | "execution_count": 48, 343 | "metadata": {}, 344 | "outputs": [ 345 | { 346 | "name": "stdout", 347 | "output_type": "stream", 348 | "text": [ 349 | "\n" 350 | ] 351 | } 352 | ], 353 | "source": [ 354 | "print(re.search(r\"p.ng\", \"sponge\"))" 355 | ] 356 | }, 357 | { 358 | "cell_type": "code", 359 | "execution_count": 49, 360 | "metadata": {}, 361 | "outputs": [ 362 | { 363 | "name": "stdout", 364 | "output_type": "stream", 365 | "text": [ 366 | "\n" 367 | ] 368 | } 369 | ], 370 | "source": [ 371 | "print(re.search(r\"p.ng\", \"p ng\"))" 372 | ] 373 | }, 374 | { 375 | "cell_type": "markdown", 376 | "metadata": {}, 377 | "source": [ 378 | "**Character class**\n", 379 | "\n", 380 | "A character class is represented by square brackets ([ ]). \n", 381 | "Anything inside the character class is considered for a given position of the pattern. \n", 382 | "For example, in the first example, both p and P are considered to be matched at the first position of the pattern." 383 | ] 384 | }, 385 | { 386 | "cell_type": "code", 387 | "execution_count": 50, 388 | "metadata": {}, 389 | "outputs": [ 390 | { 391 | "name": "stdout", 392 | "output_type": "stream", 393 | "text": [ 394 | "\n" 395 | ] 396 | } 397 | ], 398 | "source": [ 399 | "print(re.search(r\"[Pp]ing\", \"ping\"))" 400 | ] 401 | }, 402 | { 403 | "cell_type": "code", 404 | "execution_count": 51, 405 | "metadata": {}, 406 | "outputs": [ 407 | { 408 | "name": "stdout", 409 | "output_type": "stream", 410 | "text": [ 411 | "\n" 412 | ] 413 | } 414 | ], 415 | "source": [ 416 | "print(re.search(r\"[pP]ing\", \"Ping\"))" 417 | ] 418 | }, 419 | { 420 | "cell_type": "markdown", 421 | "metadata": {}, 422 | "source": [ 423 | "A character class can also contain a group or sequence of characters. \n", 424 | "For example, [a-z] represents all lower case characters." 425 | ] 426 | }, 427 | { 428 | "cell_type": "code", 429 | "execution_count": 52, 430 | "metadata": {}, 431 | "outputs": [ 432 | { 433 | "name": "stdout", 434 | "output_type": "stream", 435 | "text": [ 436 | "\n" 437 | ] 438 | } 439 | ], 440 | "source": [ 441 | "print(re.search(r\"[a-z]way\", \"The highway\"))" 442 | ] 443 | }, 444 | { 445 | "cell_type": "code", 446 | "execution_count": 53, 447 | "metadata": {}, 448 | "outputs": [ 449 | { 450 | "name": "stdout", 451 | "output_type": "stream", 452 | "text": [ 453 | "None\n" 454 | ] 455 | } 456 | ], 457 | "source": [ 458 | "print(re.search(r\"[a-z]way\", \"The way\"))" 459 | ] 460 | }, 461 | { 462 | "cell_type": "code", 463 | "execution_count": 54, 464 | "metadata": {}, 465 | "outputs": [ 466 | { 467 | "name": "stdout", 468 | "output_type": "stream", 469 | "text": [ 470 | "\n" 471 | ] 472 | } 473 | ], 474 | "source": [ 475 | "print(re.search(r\"cloud[a-zA-Z0-9]\", \"cloudy\"))" 476 | ] 477 | }, 478 | { 479 | "cell_type": "code", 480 | "execution_count": 55, 481 | "metadata": {}, 482 | "outputs": [ 483 | { 484 | "name": "stdout", 485 | "output_type": "stream", 486 | "text": [ 487 | "\n" 488 | ] 489 | } 490 | ], 491 | "source": [ 492 | "print(re.search(r\"cloud[a-zA-Z0-9]\", \"cloud9\"))" 493 | ] 494 | }, 495 | { 496 | "cell_type": "markdown", 497 | "metadata": {}, 498 | "source": [ 499 | "At times we would want our match to not contain some characters. \n", 500 | "To exclude characters from matching, we can use the caret (^) symbol inside a character class. \n", 501 | "For example, the pattern below excludes matches that have lower/upper case characters." 502 | ] 503 | }, 504 | { 505 | "cell_type": "code", 506 | "execution_count": 56, 507 | "metadata": {}, 508 | "outputs": [ 509 | { 510 | "name": "stdout", 511 | "output_type": "stream", 512 | "text": [ 513 | "\n" 514 | ] 515 | } 516 | ], 517 | "source": [ 518 | "print(re.search(r\"[^a-zA-Z]\",\"This is a sentence.\"))" 519 | ] 520 | }, 521 | { 522 | "cell_type": "code", 523 | "execution_count": 57, 524 | "metadata": {}, 525 | "outputs": [ 526 | { 527 | "name": "stdout", 528 | "output_type": "stream", 529 | "text": [ 530 | "\n" 531 | ] 532 | } 533 | ], 534 | "source": [ 535 | "print(re.search(r\"[^a-zA-Z ]\",\"This is a sentence.\"))" 536 | ] 537 | }, 538 | { 539 | "cell_type": "markdown", 540 | "metadata": {}, 541 | "source": [ 542 | "**Or**\n", 543 | "\n", 544 | "Sometimes we might want to use an or condition to match either one of two things in our string. \n", 545 | "An \"or\" is represented by the pipe (|) operator." 546 | ] 547 | }, 548 | { 549 | "cell_type": "code", 550 | "execution_count": 58, 551 | "metadata": {}, 552 | "outputs": [ 553 | { 554 | "name": "stdout", 555 | "output_type": "stream", 556 | "text": [ 557 | "\n" 558 | ] 559 | } 560 | ], 561 | "source": [ 562 | "print(re.search(r\"cat|dog\", \"nice cat\"))" 563 | ] 564 | }, 565 | { 566 | "cell_type": "code", 567 | "execution_count": 59, 568 | "metadata": {}, 569 | "outputs": [ 570 | { 571 | "name": "stdout", 572 | "output_type": "stream", 573 | "text": [ 574 | "\n" 575 | ] 576 | } 577 | ], 578 | "source": [ 579 | "print(re.search(r\"cat|dog\", \"good dog\"))" 580 | ] 581 | }, 582 | { 583 | "cell_type": "markdown", 584 | "metadata": {}, 585 | "source": [ 586 | "We can combine *or* and *findall* to find all matches in a given sentence belonging to either of our individual patterns. \n", 587 | "One can start thinking of the complex patterns that we can already match using the knowledge of regex that we have gained till now." 588 | ] 589 | }, 590 | { 591 | "cell_type": "code", 592 | "execution_count": 60, 593 | "metadata": {}, 594 | "outputs": [ 595 | { 596 | "name": "stdout", 597 | "output_type": "stream", 598 | "text": [ 599 | "\n" 600 | ] 601 | } 602 | ], 603 | "source": [ 604 | "print(re.search(r\"cat|dog\", \"I have a cat and a dog.\"))" 605 | ] 606 | }, 607 | { 608 | "cell_type": "code", 609 | "execution_count": 61, 610 | "metadata": {}, 611 | "outputs": [ 612 | { 613 | "name": "stdout", 614 | "output_type": "stream", 615 | "text": [ 616 | "['cat', 'dog']\n" 617 | ] 618 | } 619 | ], 620 | "source": [ 621 | "print(re.findall(r\"cat|dog\", \"I have a cat and a dog.\"))" 622 | ] 623 | }, 624 | { 625 | "cell_type": "markdown", 626 | "metadata": {}, 627 | "source": [ 628 | "**Quantifiers (a.k.a Repetition Qualifiers)** \n", 629 | "\n", 630 | "Till now we have only matched one instance of a character using the search function. \n", 631 | "What if we want to match things that are repeated? \n", 632 | "We can use repetition qualifiers for the same.\n", 633 | "\n", 634 | "There are three basic quantifiers that we use in regex:\n", 635 | "- The asterisk (\\*) symbol - matches the preceding character 0 or more times.\n", 636 | "- The plus (+) sign - matches the preceding character 1 or more times.\n", 637 | "- The question mark (?) - matches the preceding character 0 or 1 times." 638 | ] 639 | }, 640 | { 641 | "cell_type": "markdown", 642 | "metadata": {}, 643 | "source": [ 644 | "*The asterisk*" 645 | ] 646 | }, 647 | { 648 | "cell_type": "code", 649 | "execution_count": 62, 650 | "metadata": {}, 651 | "outputs": [ 652 | { 653 | "name": "stdout", 654 | "output_type": "stream", 655 | "text": [ 656 | "\n" 657 | ] 658 | } 659 | ], 660 | "source": [ 661 | "print(re.search(r\"Py.\", \"Python\"))" 662 | ] 663 | }, 664 | { 665 | "cell_type": "code", 666 | "execution_count": 63, 667 | "metadata": {}, 668 | "outputs": [ 669 | { 670 | "name": "stdout", 671 | "output_type": "stream", 672 | "text": [ 673 | "\n" 674 | ] 675 | } 676 | ], 677 | "source": [ 678 | "print(re.search(r\"Py.*\", \"Python\"))" 679 | ] 680 | }, 681 | { 682 | "cell_type": "code", 683 | "execution_count": 64, 684 | "metadata": {}, 685 | "outputs": [ 686 | { 687 | "name": "stdout", 688 | "output_type": "stream", 689 | "text": [ 690 | "\n" 691 | ] 692 | } 693 | ], 694 | "source": [ 695 | "print(re.search(r\"Py.*\", \"Py\"))" 696 | ] 697 | }, 698 | { 699 | "cell_type": "code", 700 | "execution_count": 65, 701 | "metadata": {}, 702 | "outputs": [ 703 | { 704 | "name": "stdout", 705 | "output_type": "stream", 706 | "text": [ 707 | "\n" 708 | ] 709 | } 710 | ], 711 | "source": [ 712 | "print(re.search(r\"Py.*\", \"Python programming\"))" 713 | ] 714 | }, 715 | { 716 | "cell_type": "code", 717 | "execution_count": 66, 718 | "metadata": {}, 719 | "outputs": [ 720 | { 721 | "name": "stdout", 722 | "output_type": "stream", 723 | "text": [ 724 | "\n" 725 | ] 726 | } 727 | ], 728 | "source": [ 729 | "print(re.search(r\"Py[a-zA-Z]*\", \"Python programming\"))" 730 | ] 731 | }, 732 | { 733 | "cell_type": "markdown", 734 | "metadata": {}, 735 | "source": [ 736 | "*The plus sign*" 737 | ] 738 | }, 739 | { 740 | "cell_type": "code", 741 | "execution_count": 67, 742 | "metadata": {}, 743 | "outputs": [ 744 | { 745 | "name": "stdout", 746 | "output_type": "stream", 747 | "text": [ 748 | "\n" 749 | ] 750 | } 751 | ], 752 | "source": [ 753 | "print(re.search(r\"o+l+\", \"goldfish\"))" 754 | ] 755 | }, 756 | { 757 | "cell_type": "code", 758 | "execution_count": 68, 759 | "metadata": {}, 760 | "outputs": [ 761 | { 762 | "name": "stdout", 763 | "output_type": "stream", 764 | "text": [ 765 | "\n" 766 | ] 767 | } 768 | ], 769 | "source": [ 770 | "print(re.search(r\"o+l+\", \"woolly\"))" 771 | ] 772 | }, 773 | { 774 | "cell_type": "code", 775 | "execution_count": 69, 776 | "metadata": { 777 | "scrolled": true 778 | }, 779 | "outputs": [ 780 | { 781 | "name": "stdout", 782 | "output_type": "stream", 783 | "text": [ 784 | "\n" 785 | ] 786 | } 787 | ], 788 | "source": [ 789 | "print(re.search(r\"o+l+\", \"wool\"))" 790 | ] 791 | }, 792 | { 793 | "cell_type": "code", 794 | "execution_count": 70, 795 | "metadata": {}, 796 | "outputs": [ 797 | { 798 | "name": "stdout", 799 | "output_type": "stream", 800 | "text": [ 801 | "None\n" 802 | ] 803 | } 804 | ], 805 | "source": [ 806 | "print(re.search(r\"o+l+\", \"boil\"))" 807 | ] 808 | }, 809 | { 810 | "cell_type": "markdown", 811 | "metadata": {}, 812 | "source": [ 813 | "*The question mark*" 814 | ] 815 | }, 816 | { 817 | "cell_type": "code", 818 | "execution_count": 71, 819 | "metadata": {}, 820 | "outputs": [ 821 | { 822 | "name": "stdout", 823 | "output_type": "stream", 824 | "text": [ 825 | "\n" 826 | ] 827 | } 828 | ], 829 | "source": [ 830 | "print(re.search(r\"p?each\", \"to each his own\"))" 831 | ] 832 | }, 833 | { 834 | "cell_type": "code", 835 | "execution_count": 72, 836 | "metadata": {}, 837 | "outputs": [ 838 | { 839 | "name": "stdout", 840 | "output_type": "stream", 841 | "text": [ 842 | "\n" 843 | ] 844 | } 845 | ], 846 | "source": [ 847 | "print(re.search(r\"p?each\", \"peachy\"))" 848 | ] 849 | }, 850 | { 851 | "cell_type": "markdown", 852 | "metadata": {}, 853 | "source": [ 854 | "**Escaping Characters** \n", 855 | "\n", 856 | "What if we want to match a given special character (like . or +)? \n", 857 | "We can use a backslash (\\) to escape special characters and treat them as literal string characters. \n", 858 | "**Note:** most special characters inside a character class are treated as literal string characters." 859 | ] 860 | }, 861 | { 862 | "cell_type": "code", 863 | "execution_count": 73, 864 | "metadata": {}, 865 | "outputs": [ 866 | { 867 | "name": "stdout", 868 | "output_type": "stream", 869 | "text": [ 870 | "\n" 871 | ] 872 | } 873 | ], 874 | "source": [ 875 | "print(re.search(r\".com\", \"www.pythoncomputer.com\"))" 876 | ] 877 | }, 878 | { 879 | "cell_type": "code", 880 | "execution_count": 74, 881 | "metadata": {}, 882 | "outputs": [ 883 | { 884 | "name": "stdout", 885 | "output_type": "stream", 886 | "text": [ 887 | "\n" 888 | ] 889 | } 890 | ], 891 | "source": [ 892 | "print(re.search(r\"\\.com\", \"www.pythoncomputer.com\"))" 893 | ] 894 | }, 895 | { 896 | "cell_type": "markdown", 897 | "metadata": {}, 898 | "source": [ 899 | "**Other uses of the backslash**" 900 | ] 901 | }, 902 | { 903 | "cell_type": "markdown", 904 | "metadata": {}, 905 | "source": [ 906 | "Some special predefined character classes are represented by a backslash following a character. \n", 907 | "* \\\\w - alphanumeric character = [a-zA-Z0-9] \n", 908 | "* \\\\s - spaces = [ \\t\\n]\n", 909 | "* \\\\d - digits = [0-9]\n", 910 | "* \\\\b - word boundaries" 911 | ] 912 | }, 913 | { 914 | "cell_type": "code", 915 | "execution_count": 75, 916 | "metadata": {}, 917 | "outputs": [ 918 | { 919 | "name": "stdout", 920 | "output_type": "stream", 921 | "text": [ 922 | "\n" 923 | ] 924 | } 925 | ], 926 | "source": [ 927 | "print(re.search(r\"\\w*\", \"This is an example.\"))" 928 | ] 929 | }, 930 | { 931 | "cell_type": "code", 932 | "execution_count": 76, 933 | "metadata": {}, 934 | "outputs": [ 935 | { 936 | "name": "stdout", 937 | "output_type": "stream", 938 | "text": [ 939 | "\n" 940 | ] 941 | } 942 | ], 943 | "source": [ 944 | "print(re.search(r\"\\w*\", \"This_is_an_example.\"))" 945 | ] 946 | }, 947 | { 948 | "cell_type": "code", 949 | "execution_count": 77, 950 | "metadata": {}, 951 | "outputs": [ 952 | { 953 | "name": "stdout", 954 | "output_type": "stream", 955 | "text": [ 956 | "\n" 957 | ] 958 | } 959 | ], 960 | "source": [ 961 | "print(re.search(r\"\\d+\", \"There are 12 months\"))" 962 | ] 963 | }, 964 | { 965 | "cell_type": "code", 966 | "execution_count": 78, 967 | "metadata": {}, 968 | "outputs": [ 969 | { 970 | "name": "stdout", 971 | "output_type": "stream", 972 | "text": [ 973 | "[' ', ' ', '\\n', ' ']\n" 974 | ] 975 | } 976 | ], 977 | "source": [ 978 | "print(re.findall(r\"\\s+\", \"Space is dark.\\nNewline darker.\"))" 979 | ] 980 | }, 981 | { 982 | "cell_type": "markdown", 983 | "metadata": {}, 984 | "source": [ 985 | "We can use word boundaries, to specify to regex that we want to match complete words, as shown here:" 986 | ] 987 | }, 988 | { 989 | "cell_type": "code", 990 | "execution_count": 79, 991 | "metadata": {}, 992 | "outputs": [ 993 | { 994 | "name": "stdout", 995 | "output_type": "stream", 996 | "text": [ 997 | "\n", 998 | "\n" 999 | ] 1000 | } 1001 | ], 1002 | "source": [ 1003 | "print(re.search(r\"a\\w+\", \"Match a word with a like awesome.\"))\n", 1004 | "print(re.search(r\"\\ba\\w+\", \"Match a word with a like awesome.\"))" 1005 | ] 1006 | }, 1007 | { 1008 | "cell_type": "markdown", 1009 | "metadata": {}, 1010 | "source": [ 1011 | "### A Basic Example\n", 1012 | "\n", 1013 | "Pattern matching Python variable names. \n", 1014 | "Variables in python follow these rules:\n", 1015 | "* contain letters, numbers or underscores\n", 1016 | "* begin with a letter or an underscore\n", 1017 | "\n", 1018 | "The pattern that matches the rules is shown below:" 1019 | ] 1020 | }, 1021 | { 1022 | "cell_type": "code", 1023 | "execution_count": 80, 1024 | "metadata": {}, 1025 | "outputs": [], 1026 | "source": [ 1027 | "pattern = r\"^[a-zA-Z_]\\w*$\"" 1028 | ] 1029 | }, 1030 | { 1031 | "cell_type": "code", 1032 | "execution_count": 81, 1033 | "metadata": {}, 1034 | "outputs": [ 1035 | { 1036 | "name": "stdout", 1037 | "output_type": "stream", 1038 | "text": [ 1039 | "\n" 1040 | ] 1041 | } 1042 | ], 1043 | "source": [ 1044 | "print(re.search(pattern, \"_this_is_a_valid_variable\"))" 1045 | ] 1046 | }, 1047 | { 1048 | "cell_type": "code", 1049 | "execution_count": 82, 1050 | "metadata": {}, 1051 | "outputs": [ 1052 | { 1053 | "name": "stdout", 1054 | "output_type": "stream", 1055 | "text": [ 1056 | "None\n" 1057 | ] 1058 | } 1059 | ], 1060 | "source": [ 1061 | "print(re.search(pattern, \"_this_is_an invalid_variable\"))" 1062 | ] 1063 | }, 1064 | { 1065 | "cell_type": "code", 1066 | "execution_count": 83, 1067 | "metadata": {}, 1068 | "outputs": [ 1069 | { 1070 | "name": "stdout", 1071 | "output_type": "stream", 1072 | "text": [ 1073 | "\n" 1074 | ] 1075 | } 1076 | ], 1077 | "source": [ 1078 | "print(re.search(pattern, \"it_can_contain_numbers123\"))" 1079 | ] 1080 | }, 1081 | { 1082 | "cell_type": "code", 1083 | "execution_count": 84, 1084 | "metadata": {}, 1085 | "outputs": [ 1086 | { 1087 | "name": "stdout", 1088 | "output_type": "stream", 1089 | "text": [ 1090 | "None\n" 1091 | ] 1092 | } 1093 | ], 1094 | "source": [ 1095 | "print(re.search(pattern, \"123cant_start_with_numbers\"))" 1096 | ] 1097 | }, 1098 | { 1099 | "cell_type": "markdown", 1100 | "metadata": {}, 1101 | "source": [ 1102 | "## Advanced RegExp" 1103 | ] 1104 | }, 1105 | { 1106 | "cell_type": "markdown", 1107 | "metadata": {}, 1108 | "source": [ 1109 | "**More Repetition Qualifiers** \n", 1110 | "\n", 1111 | "There is another type of repetition qualifier that helps us gain finer control of how many repeats we want in our matches. \n", 1112 | "The curly brackets ({}) can be used to define a range of character repetitions that we want our pattern to match in a string. \n", 1113 | "{m} - matches exactly m repeats of the preceding character. \n", 1114 | "{m, n} - matches if the preceding character is repeated at least m times and at most n times" 1115 | ] 1116 | }, 1117 | { 1118 | "cell_type": "code", 1119 | "execution_count": 85, 1120 | "metadata": {}, 1121 | "outputs": [ 1122 | { 1123 | "name": "stdout", 1124 | "output_type": "stream", 1125 | "text": [ 1126 | "\n" 1127 | ] 1128 | } 1129 | ], 1130 | "source": [ 1131 | "print(re.search(r\"\\w{5}\", \"a scary ghost appears.\"))" 1132 | ] 1133 | }, 1134 | { 1135 | "cell_type": "code", 1136 | "execution_count": 86, 1137 | "metadata": {}, 1138 | "outputs": [ 1139 | { 1140 | "name": "stdout", 1141 | "output_type": "stream", 1142 | "text": [ 1143 | "['scary', 'ghost', 'appea']\n" 1144 | ] 1145 | } 1146 | ], 1147 | "source": [ 1148 | "print(re.findall(r\"\\w{5}\", \"a scary ghost appears.\"))" 1149 | ] 1150 | }, 1151 | { 1152 | "cell_type": "markdown", 1153 | "metadata": {}, 1154 | "source": [ 1155 | "We can use a word boundary to explicitly say that we want to match full words." 1156 | ] 1157 | }, 1158 | { 1159 | "cell_type": "code", 1160 | "execution_count": 87, 1161 | "metadata": {}, 1162 | "outputs": [ 1163 | { 1164 | "name": "stdout", 1165 | "output_type": "stream", 1166 | "text": [ 1167 | "['scary', 'ghost']\n" 1168 | ] 1169 | } 1170 | ], 1171 | "source": [ 1172 | "print(re.findall(r\"\\b\\w{5}\\b\", \"a scary ghost appears.\"))" 1173 | ] 1174 | }, 1175 | { 1176 | "cell_type": "code", 1177 | "execution_count": 88, 1178 | "metadata": {}, 1179 | "outputs": [ 1180 | { 1181 | "name": "stdout", 1182 | "output_type": "stream", 1183 | "text": [ 1184 | "['scary', 'ghost', 'appears']\n" 1185 | ] 1186 | } 1187 | ], 1188 | "source": [ 1189 | "print(re.findall(r\"\\b\\w{5,10}\\b\", \"a scary ghost appears.\"))" 1190 | ] 1191 | }, 1192 | { 1193 | "cell_type": "markdown", 1194 | "metadata": {}, 1195 | "source": [ 1196 | "A number followed by a comma gives us a lower bound on the number of repeats" 1197 | ] 1198 | }, 1199 | { 1200 | "cell_type": "code", 1201 | "execution_count": 89, 1202 | "metadata": {}, 1203 | "outputs": [ 1204 | { 1205 | "name": "stdout", 1206 | "output_type": "stream", 1207 | "text": [ 1208 | "['scary', 'ghost', 'appears']\n" 1209 | ] 1210 | } 1211 | ], 1212 | "source": [ 1213 | "print(re.findall(r\"\\b\\w{5,}\\b\", \"a scary ghost appears.\"))" 1214 | ] 1215 | }, 1216 | { 1217 | "cell_type": "markdown", 1218 | "metadata": {}, 1219 | "source": [ 1220 | "A comma followed by a number gives us an upper bound on the number of repeats." 1221 | ] 1222 | }, 1223 | { 1224 | "cell_type": "code", 1225 | "execution_count": 90, 1226 | "metadata": {}, 1227 | "outputs": [ 1228 | { 1229 | "name": "stdout", 1230 | "output_type": "stream", 1231 | "text": [ 1232 | "['scary']\n" 1233 | ] 1234 | } 1235 | ], 1236 | "source": [ 1237 | "print(re.findall(r\"\\bs\\w{,5}\\b\", \"a scary ghost appears.\"))" 1238 | ] 1239 | }, 1240 | { 1241 | "cell_type": "markdown", 1242 | "metadata": {}, 1243 | "source": [ 1244 | "**Capturing Groups**\n", 1245 | "\n", 1246 | "With the help of regex, we can capture groups of characters or single characters that we match using the parentheses (()). \n", 1247 | "The match object stores the matches in a list format. \n", 1248 | "The first item is the whole matched string \n", 1249 | "The second item contains the first matched group \n", 1250 | "The third item contains the second matched group \n", 1251 | "and so on.\n", 1252 | "\n", 1253 | "Here is an example to illustrate this:" 1254 | ] 1255 | }, 1256 | { 1257 | "cell_type": "code", 1258 | "execution_count": 91, 1259 | "metadata": {}, 1260 | "outputs": [ 1261 | { 1262 | "name": "stdout", 1263 | "output_type": "stream", 1264 | "text": [ 1265 | "\n", 1266 | "('Elvis', 'Presley')\n", 1267 | "Elvis Presley\n", 1268 | "Elvis\n", 1269 | "Presley\n" 1270 | ] 1271 | } 1272 | ], 1273 | "source": [ 1274 | "result = re.search(r\"^(\\w+) (\\w+)$\", \"Elvis Presley\")\n", 1275 | "print(result)\n", 1276 | "print(result.groups())\n", 1277 | "print(result[0])\n", 1278 | "print(result[1])\n", 1279 | "print(result[2])" 1280 | ] 1281 | }, 1282 | { 1283 | "cell_type": "markdown", 1284 | "metadata": {}, 1285 | "source": [ 1286 | "Now that we have a pattern that we can use to match names. Lets stop printing and write a function that takes in a name of the form *FIRSTNAME LASTNAME* and rearranges it to the format *LASTNAME,FIRSTNAME*" 1287 | ] 1288 | }, 1289 | { 1290 | "cell_type": "code", 1291 | "execution_count": 92, 1292 | "metadata": {}, 1293 | "outputs": [], 1294 | "source": [ 1295 | "def rearrange_name(name):\n", 1296 | " result = re.search(r\"^(\\w+) (\\w+)$\", name)\n", 1297 | " if result is None:\n", 1298 | " return name\n", 1299 | " return \"{},{}\".format(result[2], result[1])" 1300 | ] 1301 | }, 1302 | { 1303 | "cell_type": "code", 1304 | "execution_count": 93, 1305 | "metadata": {}, 1306 | "outputs": [ 1307 | { 1308 | "name": "stdout", 1309 | "output_type": "stream", 1310 | "text": [ 1311 | "Presley,Elvis\n", 1312 | "Norton,Edward\n" 1313 | ] 1314 | } 1315 | ], 1316 | "source": [ 1317 | "print(rearrange_name(\"Elvis Presley\"))\n", 1318 | "print(rearrange_name(\"Edward Norton\"))" 1319 | ] 1320 | }, 1321 | { 1322 | "cell_type": "markdown", 1323 | "metadata": {}, 1324 | "source": [ 1325 | "Woohoo! We wrote our first useful function using regex. But wait, the same task can be done pretty easily with regex and without writing a function. The next part shows how." 1326 | ] 1327 | }, 1328 | { 1329 | "cell_type": "markdown", 1330 | "metadata": {}, 1331 | "source": [ 1332 | "**Splitting and Replacing** \n", 1333 | "\n", 1334 | "Apart from searching for and finding patterns, we can use the regex library to do so much more in python. \n", 1335 | "Two important uses of regex in python are splitting strings and capturing strings. \n", 1336 | "\n", 1337 | "We can use the `re.split()` method to split strings using some regex pattern or characters. \n", 1338 | "We can use the `re.sub()` method to replace a given matched pattern with a specified string." 1339 | ] 1340 | }, 1341 | { 1342 | "cell_type": "code", 1343 | "execution_count": 94, 1344 | "metadata": {}, 1345 | "outputs": [ 1346 | { 1347 | "name": "stdout", 1348 | "output_type": "stream", 1349 | "text": [ 1350 | "['One sentence', ' Another one', ' The last one', '']\n" 1351 | ] 1352 | } 1353 | ], 1354 | "source": [ 1355 | "print(re.split(r\"[.?!]\",\"One sentence. Another one? The last one!\"))" 1356 | ] 1357 | }, 1358 | { 1359 | "cell_type": "code", 1360 | "execution_count": 95, 1361 | "metadata": {}, 1362 | "outputs": [ 1363 | { 1364 | "name": "stdout", 1365 | "output_type": "stream", 1366 | "text": [ 1367 | "['One sentence', '.', ' Another one', '?', ' The last one', '!', '']\n" 1368 | ] 1369 | } 1370 | ], 1371 | "source": [ 1372 | "print(re.split(r\"([.?!])\",\"One sentence. Another one? The last one!\"))" 1373 | ] 1374 | }, 1375 | { 1376 | "cell_type": "code", 1377 | "execution_count": 96, 1378 | "metadata": {}, 1379 | "outputs": [ 1380 | { 1381 | "name": "stdout", 1382 | "output_type": "stream", 1383 | "text": [ 1384 | "Received email from [REDACTED]\n" 1385 | ] 1386 | } 1387 | ], 1388 | "source": [ 1389 | "print(re.sub(r\"[\\w.%+-]+@[\\w.-]+\", \"[REDACTED]\", \"Received email from lol@google.com\"))" 1390 | ] 1391 | }, 1392 | { 1393 | "cell_type": "markdown", 1394 | "metadata": {}, 1395 | "source": [ 1396 | "We can reference captured groups by using the backslash followed by the index at which the match is stored in the list of matches. \n", 1397 | "Equipped with this new piece of information and the `re.sub` function, we can now write the rearrange_name function in a much shorter way:" 1398 | ] 1399 | }, 1400 | { 1401 | "cell_type": "code", 1402 | "execution_count": 97, 1403 | "metadata": {}, 1404 | "outputs": [ 1405 | { 1406 | "name": "stdout", 1407 | "output_type": "stream", 1408 | "text": [ 1409 | "Elvis,Presley\n" 1410 | ] 1411 | } 1412 | ], 1413 | "source": [ 1414 | "print(re.sub(r\"(\\w+) (\\w+)\", r\"\\1,\\2\", \"Elvis Presley\"))" 1415 | ] 1416 | }, 1417 | { 1418 | "cell_type": "markdown", 1419 | "metadata": {}, 1420 | "source": [ 1421 | "**Backreferencing**\n", 1422 | "\n", 1423 | "We learned that we can reference captured groups by using a backslash and the index of the group. \n", 1424 | "We can also use the backslash and index to reference a captured group from within the pattern itself. This is known as backreferencing. \n", 1425 | "There can be lots of uses of backreferencing and it is quite an advanced regex concept. But we will look at a small example of where it might help." 1426 | ] 1427 | }, 1428 | { 1429 | "cell_type": "markdown", 1430 | "metadata": {}, 1431 | "source": [ 1432 | "We want to match two repeats of the same word, but we don't know what exactly the word is. \n", 1433 | "How can we approach this problem using regex?" 1434 | ] 1435 | }, 1436 | { 1437 | "cell_type": "code", 1438 | "execution_count": 98, 1439 | "metadata": {}, 1440 | "outputs": [ 1441 | { 1442 | "name": "stdout", 1443 | "output_type": "stream", 1444 | "text": [ 1445 | "\n" 1446 | ] 1447 | } 1448 | ], 1449 | "source": [ 1450 | "print(re.search(r\"(\\w+) (\\w+)\", \"okay okay\"))" 1451 | ] 1452 | }, 1453 | { 1454 | "cell_type": "code", 1455 | "execution_count": 99, 1456 | "metadata": {}, 1457 | "outputs": [ 1458 | { 1459 | "name": "stdout", 1460 | "output_type": "stream", 1461 | "text": [ 1462 | "\n" 1463 | ] 1464 | } 1465 | ], 1466 | "source": [ 1467 | "print(re.search(r\"(\\w+) (\\w+)\", \"alright alright\"))" 1468 | ] 1469 | }, 1470 | { 1471 | "cell_type": "markdown", 1472 | "metadata": {}, 1473 | "source": [ 1474 | "The above pattern seems to match what we want right? \n", 1475 | "Let's look at a different string." 1476 | ] 1477 | }, 1478 | { 1479 | "cell_type": "code", 1480 | "execution_count": 100, 1481 | "metadata": {}, 1482 | "outputs": [ 1483 | { 1484 | "name": "stdout", 1485 | "output_type": "stream", 1486 | "text": [ 1487 | "\n" 1488 | ] 1489 | } 1490 | ], 1491 | "source": [ 1492 | "print(re.search(r\"(\\w+) (\\w+)\", \"okay alright\"))" 1493 | ] 1494 | }, 1495 | { 1496 | "cell_type": "markdown", 1497 | "metadata": {}, 1498 | "source": [ 1499 | "This is an issue, although we will match all the words that we wanted to match, we will also match words other than the correct matches.\n", 1500 | "\n", 1501 | "Backreferencing to the rescue! \n", 1502 | "By *backreferencing* the first captured group, we can ensure that the second word matches the first one that found. Thus, we can match the correct words that we want and steer clear of the incorrect matches." 1503 | ] 1504 | }, 1505 | { 1506 | "cell_type": "code", 1507 | "execution_count": 101, 1508 | "metadata": {}, 1509 | "outputs": [ 1510 | { 1511 | "name": "stdout", 1512 | "output_type": "stream", 1513 | "text": [ 1514 | "\n" 1515 | ] 1516 | } 1517 | ], 1518 | "source": [ 1519 | "print(re.search(r\"(\\w+) \\1\", \"okay okay\"))" 1520 | ] 1521 | }, 1522 | { 1523 | "cell_type": "code", 1524 | "execution_count": 102, 1525 | "metadata": {}, 1526 | "outputs": [ 1527 | { 1528 | "name": "stdout", 1529 | "output_type": "stream", 1530 | "text": [ 1531 | "\n" 1532 | ] 1533 | } 1534 | ], 1535 | "source": [ 1536 | "print(re.search(r\"(\\w+) \\1\", \"alright alright\"))" 1537 | ] 1538 | }, 1539 | { 1540 | "cell_type": "code", 1541 | "execution_count": 103, 1542 | "metadata": { 1543 | "scrolled": true 1544 | }, 1545 | "outputs": [ 1546 | { 1547 | "name": "stdout", 1548 | "output_type": "stream", 1549 | "text": [ 1550 | "None\n" 1551 | ] 1552 | } 1553 | ], 1554 | "source": [ 1555 | "print(re.search(r\"(\\w+) \\1\", \"okay alright\"))" 1556 | ] 1557 | }, 1558 | { 1559 | "cell_type": "markdown", 1560 | "metadata": {}, 1561 | "source": [ 1562 | "Phew! That was a lot. Have a second look, try experimenting and trying out different ideas and matches. \n", 1563 | "Feel free to use this notebook as a cheat sheet for regex in Python." 1564 | ] 1565 | } 1566 | ], 1567 | "metadata": { 1568 | "kernelspec": { 1569 | "display_name": "Python 3", 1570 | "language": "python", 1571 | "name": "python3" 1572 | }, 1573 | "language_info": { 1574 | "codemirror_mode": { 1575 | "name": "ipython", 1576 | "version": 3 1577 | }, 1578 | "file_extension": ".py", 1579 | "mimetype": "text/x-python", 1580 | "name": "python", 1581 | "nbconvert_exporter": "python", 1582 | "pygments_lexer": "ipython3", 1583 | "version": "3.8.3" 1584 | } 1585 | }, 1586 | "nbformat": 4, 1587 | "nbformat_minor": 4 1588 | } 1589 | -------------------------------------------------------------------------------- /Python-Notebooks/5.Working with Files and Directories.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Working with Files and Directories in Python\n", 8 | "\n", 9 | "**By Arpit Omprakash, Byte Sized Code**" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "## Files" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "**Import os module for working with files**\n", 24 | "\n", 25 | "The `os` module contains functions that we can use to interact appropriately with our operating system. \n", 26 | "It contains functions that let us manipulate and manage files as if we were working in our native os \"shell.\"" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 48, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "import os" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "**Creating a file**\n", 43 | "\n", 44 | "We can use the built-in function `open` to create a file in python. \n", 45 | "`open` takes in two arguments:\n", 46 | "* filename - This can be the absolute or relative path to the file you want to access\n", 47 | "* mode - The mode for accessing the file\n", 48 | "\n", 49 | "The \"w+\" mode is composed of \"w\" and \"+\".\n", 50 | "* the 'w' indicates we want to write to a file\n", 51 | "* the '+' instructs python to create a file if not present currently\n", 52 | "\n", 53 | "**Opening and Closing Files**\n", 54 | "\n", 55 | "Just like you would with any other application (or the default file viewer), while using python we have to open and close files. Opening files help us to manipulate them and closing them tells the `os` that we don't need to deal with the files anymore. The `os` then allows other applications to access the file and frees up any resources that would have been used otherwise." 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 49, 61 | "metadata": {}, 62 | "outputs": [], 63 | "source": [ 64 | "f = open(\"first_draft.txt\", \"w+\")\n", 65 | "f.close()" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": {}, 71 | "source": [ 72 | "**Writing to a file**\n", 73 | "\n", 74 | "As mentioned above, we can use only the \"w\" to indicate that we want to write to the file. \n", 75 | "Then, we write to the file using the `file.write()` function." 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 50, 81 | "metadata": {}, 82 | "outputs": [], 83 | "source": [ 84 | "f = open(\"first_draft.txt\", \"w\")\n", 85 | "f.write(\"Twinkle twinkle little star \\nHow I wonder what you are? \\n\")\n", 86 | "f.close()" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "**Appending to a file**\n", 94 | "\n", 95 | "There is a major issue (according to me) in how we write to files in python. \n", 96 | "If you run the above cell again, contrary to what you might expect, the output is the same as before. \n", 97 | "The \"w\" mode always clears a file before opening it in write mode. \n", 98 | "Thus, writing to a file is technically \"overwriting.\"\n", 99 | "\n", 100 | "*But what if we want to just add things at the end of a file?* \n", 101 | "We use another mode for the same, called the \"append\" mode and it is indicated by an \"a.\"" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 51, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [ 110 | "with open(\"first_draft.txt\", \"a\") as f:\n", 111 | " f.write(\"Up above the world so high \\nLike a diamond in the sky\")" 112 | ] 113 | }, 114 | { 115 | "cell_type": "markdown", 116 | "metadata": {}, 117 | "source": [ 118 | "Ah, the `with` keyword. \n", 119 | "In the last cell, we basically use a python keyword called `with` to handle the file opening and closing by itself. Thus, we don't have to remember to open and close our files manually. The only downside is that, we have to write all our file manipulation code inside the `with` block.\n", 120 | "\n", 121 | "The `with` keyword belongs to something called a **context manager** in Python. Context Managers help simplify the resource use and allocation in our python operations. You can read more about context managers [here](https://book.pythontips.com/en/latest/context_managers.html)" 122 | ] 123 | }, 124 | { 125 | "cell_type": "markdown", 126 | "metadata": {}, 127 | "source": [ 128 | "**Reading data from a file**\n", 129 | "\n", 130 | "Now that we know how to write and append to a file, let's learn how we can get data from a file. \n", 131 | "We use the \"read\" or \"r\" mode to read data from a file." 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": 52, 137 | "metadata": {}, 138 | "outputs": [ 139 | { 140 | "name": "stdout", 141 | "output_type": "stream", 142 | "text": [ 143 | "Twinkle twinkle little star \n", 144 | "\n", 145 | "How I wonder what you are? \n", 146 | "\n", 147 | "Up above the world so high \n", 148 | "\n", 149 | "Like a diamond in the sky\n" 150 | ] 151 | } 152 | ], 153 | "source": [ 154 | "with open(\"first_draft.txt\", \"r\") as f:\n", 155 | " for line in f:\n", 156 | " print(line)" 157 | ] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "metadata": {}, 162 | "source": [ 163 | "**Renaming a file**\n", 164 | "\n", 165 | "We can use the intuitive `os.rename()` function to rename files. \n", 166 | "The rename function takes two arguments,\n", 167 | "* filename (and location)\n", 168 | "* new name (and location)\n", 169 | "\n", 170 | "The location can be relative or absolute." 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": 53, 176 | "metadata": {}, 177 | "outputs": [], 178 | "source": [ 179 | "os.rename(\"first_draft.txt\", \"rhyme.txt\")" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "**Checking the size of a file**\n", 187 | "\n", 188 | "The `os.path.getsize()` returns the size of the file in bytes. \n", 189 | "It takes the absolute/relative path to the file." 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": 54, 195 | "metadata": {}, 196 | "outputs": [ 197 | { 198 | "data": { 199 | "text/plain": [ 200 | "113" 201 | ] 202 | }, 203 | "execution_count": 54, 204 | "metadata": {}, 205 | "output_type": "execute_result" 206 | } 207 | ], 208 | "source": [ 209 | "os.path.getsize(\"rhyme.txt\")" 210 | ] 211 | }, 212 | { 213 | "cell_type": "markdown", 214 | "metadata": {}, 215 | "source": [ 216 | "**Check when a file was last modified**\n", 217 | "\n", 218 | "We can use the `os.path.getmtime()` function to get the time when a given file was last modified. \n", 219 | "The function takes the absolute/relative path to the file as the argument. \n", 220 | "The function returns a [UNIX timestamp](https://en.wikipedia.org/wiki/Unix_time) which we can convert into a more readable format by using the `datetime` library." 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": 55, 226 | "metadata": {}, 227 | "outputs": [ 228 | { 229 | "data": { 230 | "text/plain": [ 231 | "datetime.datetime(2020, 9, 10, 20, 29, 16, 503171)" 232 | ] 233 | }, 234 | "execution_count": 55, 235 | "metadata": {}, 236 | "output_type": "execute_result" 237 | } 238 | ], 239 | "source": [ 240 | "import datetime\n", 241 | "\n", 242 | "timestamp = os.path.getmtime(\"rhyme.txt\")\n", 243 | "datetime.datetime.fromtimestamp(timestamp)" 244 | ] 245 | }, 246 | { 247 | "cell_type": "markdown", 248 | "metadata": {}, 249 | "source": [ 250 | "**Check if a file exists**\n", 251 | "\n", 252 | "There are two functions that can check whether a file exists. \n", 253 | "Both the functions are present in the `path` submodule and take the file path as input.\n", 254 | "\n", 255 | "The first is the `isfile()` function and the second is the `exists()` function. \n", 256 | "They return `True` if the file is present and `False` otherwise." 257 | ] 258 | }, 259 | { 260 | "cell_type": "code", 261 | "execution_count": 56, 262 | "metadata": {}, 263 | "outputs": [ 264 | { 265 | "data": { 266 | "text/plain": [ 267 | "False" 268 | ] 269 | }, 270 | "execution_count": 56, 271 | "metadata": {}, 272 | "output_type": "execute_result" 273 | } 274 | ], 275 | "source": [ 276 | "os.path.isfile(\"first_draft.txt\")" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": 57, 282 | "metadata": {}, 283 | "outputs": [ 284 | { 285 | "data": { 286 | "text/plain": [ 287 | "True" 288 | ] 289 | }, 290 | "execution_count": 57, 291 | "metadata": {}, 292 | "output_type": "execute_result" 293 | } 294 | ], 295 | "source": [ 296 | "os.path.exists(\"rhyme.txt\")" 297 | ] 298 | }, 299 | { 300 | "cell_type": "markdown", 301 | "metadata": {}, 302 | "source": [ 303 | "**Get absolute path to a file**\n", 304 | "\n", 305 | "The `os.path.abspath()` function is used to return the absolute path to a given file. It takes the relative path as input." 306 | ] 307 | }, 308 | { 309 | "cell_type": "code", 310 | "execution_count": 58, 311 | "metadata": {}, 312 | "outputs": [ 313 | { 314 | "name": "stdout", 315 | "output_type": "stream", 316 | "text": [ 317 | "C:\\Users\\ARPIT\\Documents\\GitHub\\Byte-Sized-Code\\Python-Notebooks\\rhyme.txt\n" 318 | ] 319 | } 320 | ], 321 | "source": [ 322 | "print(os.path.abspath(\"rhyme.txt\"))" 323 | ] 324 | }, 325 | { 326 | "cell_type": "markdown", 327 | "metadata": {}, 328 | "source": [ 329 | "**Deleting a file**\n", 330 | "\n", 331 | "The `os.remove()` function takes in the path to a given file and then deletes the file." 332 | ] 333 | }, 334 | { 335 | "cell_type": "code", 336 | "execution_count": 59, 337 | "metadata": {}, 338 | "outputs": [ 339 | { 340 | "data": { 341 | "text/plain": [ 342 | "False" 343 | ] 344 | }, 345 | "execution_count": 59, 346 | "metadata": {}, 347 | "output_type": "execute_result" 348 | } 349 | ], 350 | "source": [ 351 | "os.remove(\"rhyme.txt\")\n", 352 | "os.path.exists(\"rhyme.txt\")" 353 | ] 354 | }, 355 | { 356 | "cell_type": "markdown", 357 | "metadata": {}, 358 | "source": [ 359 | "## Directories" 360 | ] 361 | }, 362 | { 363 | "cell_type": "markdown", 364 | "metadata": {}, 365 | "source": [ 366 | "**Show the files in the current directory**\n", 367 | "\n", 368 | "The `os.listdir()` function lists all the files and sub-directories at a given directory. \n", 369 | "By default it returns files in the current directory, but you can supply it with the absolute/relative path to any other directory and get information regarding the same.\n", 370 | "\n", 371 | "The **`os.path.isdir()`** function let's us know if a given item is a directory or not. \n", 372 | "If the provided object is a directory, it returns `True` else it returns `False`." 373 | ] 374 | }, 375 | { 376 | "cell_type": "code", 377 | "execution_count": 60, 378 | "metadata": { 379 | "scrolled": true 380 | }, 381 | "outputs": [ 382 | { 383 | "data": { 384 | "text/plain": [ 385 | "['.ipynb_checkpoints', 'venv', 'Working with Files.ipynb']" 386 | ] 387 | }, 388 | "execution_count": 60, 389 | "metadata": {}, 390 | "output_type": "execute_result" 391 | } 392 | ], 393 | "source": [ 394 | "os.listdir()" 395 | ] 396 | }, 397 | { 398 | "cell_type": "code", 399 | "execution_count": 61, 400 | "metadata": {}, 401 | "outputs": [ 402 | { 403 | "name": "stdout", 404 | "output_type": "stream", 405 | "text": [ 406 | ".ipynb_checkpoints is a directory\n", 407 | "venv is a directory\n", 408 | "Working with Files.ipynb is a file\n" 409 | ] 410 | } 411 | ], 412 | "source": [ 413 | "# print if a given item is directory or file in the working directory\n", 414 | "dir = os.getcwd()\n", 415 | "for name in os.listdir(dir):\n", 416 | " if os.path.isdir(name):\n", 417 | " print(\"{} is a directory\".format(name))\n", 418 | " else:\n", 419 | " print(\"{} is a file\".format(name))" 420 | ] 421 | }, 422 | { 423 | "cell_type": "markdown", 424 | "metadata": {}, 425 | "source": [ 426 | "**Current directory**\n", 427 | "\n", 428 | "We can get the path to the current directory (the directory we are currently in) by using the `os.getcwd()` function." 429 | ] 430 | }, 431 | { 432 | "cell_type": "code", 433 | "execution_count": 62, 434 | "metadata": {}, 435 | "outputs": [ 436 | { 437 | "name": "stdout", 438 | "output_type": "stream", 439 | "text": [ 440 | "C:\\Users\\ARPIT\\Documents\\GitHub\\Byte-Sized-Code\\Python-Notebooks\n" 441 | ] 442 | } 443 | ], 444 | "source": [ 445 | "print(os.getcwd())" 446 | ] 447 | }, 448 | { 449 | "cell_type": "markdown", 450 | "metadata": {}, 451 | "source": [ 452 | "**Create a new directory**\n", 453 | "\n", 454 | "We can use the `os.mkdir()` function to create a new directory. \n", 455 | "The function takes the name of the directory that we want to create as input." 456 | ] 457 | }, 458 | { 459 | "cell_type": "code", 460 | "execution_count": 63, 461 | "metadata": {}, 462 | "outputs": [ 463 | { 464 | "data": { 465 | "text/plain": [ 466 | "['.ipynb_checkpoints', 'new_dir', 'venv', 'Working with Files.ipynb']" 467 | ] 468 | }, 469 | "execution_count": 63, 470 | "metadata": {}, 471 | "output_type": "execute_result" 472 | } 473 | ], 474 | "source": [ 475 | "os.mkdir(\"new_dir\")\n", 476 | "os.listdir()" 477 | ] 478 | }, 479 | { 480 | "cell_type": "markdown", 481 | "metadata": {}, 482 | "source": [ 483 | "**Change working directory**\n", 484 | "\n", 485 | "We can also change the directory we are working in from our python shell! \n", 486 | "The `os.chdir()` function takes in the path to the directory that we want to go to and then changes the current directory to the one provided." 487 | ] 488 | }, 489 | { 490 | "cell_type": "code", 491 | "execution_count": 64, 492 | "metadata": {}, 493 | "outputs": [ 494 | { 495 | "name": "stdout", 496 | "output_type": "stream", 497 | "text": [ 498 | "C:\\Users\\ARPIT\\Documents\\GitHub\\Byte-Sized-Code\\Python-Notebooks\\new_dir\n", 499 | "C:\\Users\\ARPIT\\Documents\\GitHub\\Byte-Sized-Code\\Python-Notebooks\n" 500 | ] 501 | } 502 | ], 503 | "source": [ 504 | "os.chdir(\"new_dir\")\n", 505 | "print(os.getcwd())\n", 506 | "os.chdir(\"..\")\n", 507 | "print(os.getcwd())" 508 | ] 509 | }, 510 | { 511 | "cell_type": "markdown", 512 | "metadata": {}, 513 | "source": [ 514 | "**Remove a directory**\n", 515 | "\n", 516 | "The `os.rmdir()` function takes in the path to the directory that we want to remove and then deletes the directory. \n", 517 | "rmdir works only if directory is empty. Otherwise we have to remove all the sub directories and files before we can remove the directory" 518 | ] 519 | }, 520 | { 521 | "cell_type": "code", 522 | "execution_count": 65, 523 | "metadata": {}, 524 | "outputs": [ 525 | { 526 | "data": { 527 | "text/plain": [ 528 | "['.ipynb_checkpoints', 'venv', 'Working with Files.ipynb']" 529 | ] 530 | }, 531 | "execution_count": 65, 532 | "metadata": {}, 533 | "output_type": "execute_result" 534 | } 535 | ], 536 | "source": [ 537 | "os.rmdir(\"new_dir\")\n", 538 | "os.listdir()" 539 | ] 540 | } 541 | ], 542 | "metadata": { 543 | "kernelspec": { 544 | "display_name": "Python 3", 545 | "language": "python", 546 | "name": "python3" 547 | }, 548 | "language_info": { 549 | "codemirror_mode": { 550 | "name": "ipython", 551 | "version": 3 552 | }, 553 | "file_extension": ".py", 554 | "mimetype": "text/x-python", 555 | "name": "python", 556 | "nbconvert_exporter": "python", 557 | "pygments_lexer": "ipython3", 558 | "version": "3.8.3" 559 | } 560 | }, 561 | "nbformat": 4, 562 | "nbformat_minor": 4 563 | } 564 | -------------------------------------------------------------------------------- /Python-Notebooks/6.Working with CSV files.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Working with CSV Files\n", 8 | "\n", 9 | "**By Arpit Omprakash, Byte Sized Code**" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "**Import the csv module**\n", 17 | "\n", 18 | "To make things easy, we will use the `csv` library from the Python standard library." 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 23, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "import csv" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "## Generating CSV Files\n", 35 | "\n", 36 | "We can use either lists or dictionaries to generate csv data and files. \n", 37 | "Let's use lists to create an `employee.csv` file that stores data about some employees." 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "**Using lists**\n", 45 | "\n", 46 | "First we need to create a list of employees." 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 24, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "employees = [[\"Sabrina\", 9567622648, \"IT support\"], [\"John\", 9456721352, \"Sysadmin\"], [\"Kelly\", 9645871235, \"Receptionist\"]]" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "Using the `csv.writer` class, we create a writer object that will write into our csv files properly. \n", 63 | "The `writer` class takes in a file as argument. \n", 64 | "We use the `writerows` method of the `writer` class to write more than one row of data to our csv file. \n", 65 | "We can also use the `writerow` method to write a single row of data to our file.\n", 66 | "\n", 67 | "According to the [docs](https://docs.python.org/3/library/csv.html#csv.writer), while writing to file objects, we have to include the `newline=''` argument to prevent the `writer` class from writing empty lines to our file." 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 25, 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [ 76 | "with open(\"employee.csv\", \"w+\", newline='') as employee_file:\n", 77 | " writer = csv.writer(employee_file)\n", 78 | " writer.writerows(employees)" 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": {}, 84 | "source": [ 85 | "Let's open up the csv file and read the contents as we would with any other file." 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 26, 91 | "metadata": {}, 92 | "outputs": [ 93 | { 94 | "name": "stdout", 95 | "output_type": "stream", 96 | "text": [ 97 | "Sabrina,9567622648,IT support\n", 98 | "John,9456721352,Sysadmin\n", 99 | "Kelly,9645871235,Receptionist\n" 100 | ] 101 | } 102 | ], 103 | "source": [ 104 | "with open(\"employee.csv\") as employee_file:\n", 105 | " for line in employee_file:\n", 106 | " print(line.strip())" 107 | ] 108 | }, 109 | { 110 | "cell_type": "markdown", 111 | "metadata": {}, 112 | "source": [ 113 | "**Using dictionaries**\n", 114 | "\n", 115 | "We can also use dictionaries to write data to csv file. \n", 116 | "Dictionaries help make things easier by providing headers for the data that we want to write to the files. \n", 117 | "Keep in mind, we need to define a list containing the data for the header row (column names) before writing dictionaries to csv.\n", 118 | "\n", 119 | "In this example, we use a dictionary to create a csv file that stores data about some softwares." 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 27, 125 | "metadata": {}, 126 | "outputs": [], 127 | "source": [ 128 | "softwares = [\n", 129 | " {\"name\": \"Chatty Chicken\", \"version\": \"1.02.03\", \"users\": 54},\n", 130 | " {\"name\": \"Coder Kitchen\", \"version\": \"1.32.30\", \"users\": 104},\n", 131 | " {\"name\": \"Sensible Writer\", \"version\": \"4.1.03\", \"users\": 454},\n", 132 | " {\"name\": \"Magic Image Viewer\", \"version\": \"0.1.20\", \"users\": 4},\n", 133 | " ]\n", 134 | "keys = [\"name\", \"version\", \"users\"]" 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "For writing dictionaries to csv files, we use the `csv.DictWriter` class. \n", 142 | "The class takes the file as an argument. \n", 143 | "We also provide the header data to the `fieldnames` argument. \n", 144 | "The `writeheader()` method is called first and it writes the header as the first line of the file. \n", 145 | "Then we use the `writerows()` method to write data using the dictionary." 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": 28, 151 | "metadata": {}, 152 | "outputs": [], 153 | "source": [ 154 | "with open(\"software.csv\", \"w+\", newline='') as software_file:\n", 155 | " writer = csv.DictWriter(software_file, fieldnames=keys)\n", 156 | " writer.writeheader()\n", 157 | " writer.writerows(softwares)" 158 | ] 159 | }, 160 | { 161 | "cell_type": "markdown", 162 | "metadata": {}, 163 | "source": [ 164 | "Let's have a look at what we just wrote to the csv file." 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": 29, 170 | "metadata": {}, 171 | "outputs": [ 172 | { 173 | "name": "stdout", 174 | "output_type": "stream", 175 | "text": [ 176 | "name,version,users\n", 177 | "Chatty Chicken,1.02.03,54\n", 178 | "Coder Kitchen,1.32.30,104\n", 179 | "Sensible Writer,4.1.03,454\n", 180 | "Magic Image Viewer,0.1.20,4\n" 181 | ] 182 | } 183 | ], 184 | "source": [ 185 | "with open(\"software.csv\") as software_file:\n", 186 | " for line in software_file:\n", 187 | " print(line.strip())" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "## Reading data from CSV Files\n", 195 | "\n", 196 | "In the cells above we just used the `open()` function and a for loop to print out the contents of files. \n", 197 | "That is not what we want to do while manipulating and dealing with CSV data. \n", 198 | "Ideally, we should read the data in the form of rows and columns as it makes life easier and we can access individual datapoints with relative ease." 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "metadata": {}, 204 | "source": [ 205 | "**Without headers**\n", 206 | "\n", 207 | "To read a csv file without headers, we use the `csv.reader()` class. \n", 208 | "The class takes in the file as an argument. \n", 209 | "We can then access data from the file in the form of rows and columns. \n", 210 | "\n", 211 | "For example, if we want to print out the names of employees from the \"employee.csv\" file, we can use the following code:" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": 30, 217 | "metadata": {}, 218 | "outputs": [ 219 | { 220 | "name": "stdout", 221 | "output_type": "stream", 222 | "text": [ 223 | "Sabrina\n", 224 | "John\n", 225 | "Kelly\n" 226 | ] 227 | } 228 | ], 229 | "source": [ 230 | "with open(\"employee.csv\") as f:\n", 231 | " csv_f = csv.reader(f)\n", 232 | " for row in csv_f:\n", 233 | " print(row[0])" 234 | ] 235 | }, 236 | { 237 | "cell_type": "markdown", 238 | "metadata": {}, 239 | "source": [ 240 | "A better method would be to unpack the given row into its individual columns and then print the data. \n", 241 | "A downside here is that, we need to know what all columns are present in the file and unpack accordingly (we have to write name first, then phone and finally role, if we change the order, the data won't match the variable)." 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 31, 247 | "metadata": {}, 248 | "outputs": [ 249 | { 250 | "name": "stdout", 251 | "output_type": "stream", 252 | "text": [ 253 | "Name: Sabrina, Phone: 9567622648, Role: IT support\n", 254 | "Name: John, Phone: 9456721352, Role: Sysadmin\n", 255 | "Name: Kelly, Phone: 9645871235, Role: Receptionist\n" 256 | ] 257 | } 258 | ], 259 | "source": [ 260 | "with open(\"employee.csv\") as f:\n", 261 | " csv_f = csv.reader(f)\n", 262 | " for row in csv_f:\n", 263 | " name, phone, role = row\n", 264 | " print(\"Name: {}, Phone: {}, Role: {}\".format(name, phone, role))" 265 | ] 266 | }, 267 | { 268 | "cell_type": "markdown", 269 | "metadata": {}, 270 | "source": [ 271 | "**With headers**\n", 272 | "\n", 273 | "*What if we don't know what columns contain what data? \n", 274 | "Or we have a csv file with headers?*\n", 275 | "\n", 276 | "The better class to use here would be `csv.DictReader` \n", 277 | "Using this class we can access the columns from our data by using the column headers. \n", 278 | "We don't have to remember the order of columns anymore. Yay!" 279 | ] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "execution_count": 32, 284 | "metadata": {}, 285 | "outputs": [ 286 | { 287 | "name": "stdout", 288 | "output_type": "stream", 289 | "text": [ 290 | "Chatty Chicken has 54 users\n", 291 | "Coder Kitchen has 104 users\n", 292 | "Sensible Writer has 454 users\n", 293 | "Magic Image Viewer has 4 users\n" 294 | ] 295 | } 296 | ], 297 | "source": [ 298 | "with open(\"software.csv\") as software:\n", 299 | " reader = csv.DictReader(software)\n", 300 | " for row in reader:\n", 301 | " print(\"{} has {} users\".format(row[\"name\"], row[\"users\"]))" 302 | ] 303 | } 304 | ], 305 | "metadata": { 306 | "kernelspec": { 307 | "display_name": "Python 3", 308 | "language": "python", 309 | "name": "python3" 310 | }, 311 | "language_info": { 312 | "codemirror_mode": { 313 | "name": "ipython", 314 | "version": 3 315 | }, 316 | "file_extension": ".py", 317 | "mimetype": "text/x-python", 318 | "name": "python", 319 | "nbconvert_exporter": "python", 320 | "pygments_lexer": "ipython3", 321 | "version": "3.8.3" 322 | } 323 | }, 324 | "nbformat": 4, 325 | "nbformat_minor": 4 326 | } 327 | -------------------------------------------------------------------------------- /Python-Notebooks/Python-OOP.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# OOP IN PYTHON \n", 8 | "**By Muhammad Kareem**\n", 9 | "\n", 10 | "\n", 11 | "\n", 12 | "### What is OOP ?\n", 13 | "\n", 14 | "OOP or object-oriented programming is a programming paradigm that helps software developers create more maintainable and scalable\n", 15 | "\n", 16 | "### Why oop ?\n", 17 | "\n", 18 | "As mentioned above, this paradigm solves many problems in writing software as it creates like a \"template\" which other components can use and this helps reduce code and make it easier to maintain and debug if anything goes wrong\n", 19 | "\n", 20 | "### Features of oop\n", 21 | "\n", 22 | "1. Encapsulation \n", 23 | "Encapsulation refers to the creation of self-contained modules that bind processing functions to the data. These user-defined data types are called \"classes,\" and one instance of a class is an \"object.\" For example, in a payroll system, a class could be Manager, and Pat and Jan could be two instances (two objects) of the Manager class. Encapsulation ensures good code modularity, which keeps routines separate and less prone to conflict with each other.\n", 24 | "\n", 25 | "\n", 26 | "2. Inheritance\n", 27 | "Classes are created in hierarchies, and inheritance allows the structure and methods in one class to be passed down the hierarchy. That means less programming is required when adding functions to complex systems. If a step is added at the bottom of a hierarchy, only the processing and data associated with that unique step needs to be added. Everything else is inherited. The ability to reuse existing objects is considered a major advantage of object technology.\n", 28 | "\n", 29 | "\n", 30 | "3. Polymorphism\n", 31 | "Object-oriented programming allows procedures about objects to be created whose exact type is not known until runtime. For example, a screen cursor may change its shape from an arrow to a line depending on the program mode. The routine to move the cursor on screen in response to mouse movement would be written for \"cursor,\" and polymorphism allows that cursor to take on whatever shape is required at runtime. It also allows new shapes to be easily integrated." 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 2, 37 | "metadata": {}, 38 | "outputs": [ 39 | { 40 | "data": { 41 | "text/plain": [ 42 | "'Clark can fly now'" 43 | ] 44 | }, 45 | "execution_count": 2, 46 | "metadata": {}, 47 | "output_type": "execute_result" 48 | } 49 | ], 50 | "source": [ 51 | "# AN EXAMPLE OF OOP\n", 52 | "\n", 53 | "class superman:\n", 54 | " def __init__(self,name,age,job):\n", 55 | " self.name = name\n", 56 | " self.age = age\n", 57 | " self.job = job\n", 58 | " \n", 59 | " def fly(self):\n", 60 | " return f\"{self.name} can fly now\"\n", 61 | " \n", 62 | " def lift_heavy_stuff(self,item):\n", 63 | " return f\"{self.name} is now carrying an entire {item}!\"\n", 64 | "\n", 65 | "clark = superman('Clark',33,'journalist')\n", 66 | "clark.fly()" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 3, 72 | "metadata": {}, 73 | "outputs": [ 74 | { 75 | "data": { 76 | "text/plain": [ 77 | "'Clark is now carrying an entire plane!'" 78 | ] 79 | }, 80 | "execution_count": 3, 81 | "metadata": {}, 82 | "output_type": "execute_result" 83 | } 84 | ], 85 | "source": [ 86 | "clark.lift_heavy_stuff('plane')" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "### Example explained\n", 94 | "\n", 95 | "Now what's going on up there ! to define a class in python we first type the keyword *class* followed by the name of the class then we proceed to structure this class as the following\n", 96 | "Firstly we need to understand what is this `def __init__()` method, this method initializes an instance of the class, now you're still thinking WHAT THE HECK DOES THAT MEAN !!!!!!! simply put, a class is a **template** a pre defined unique variable type we decide what it can and can't do and *clark* variable here is a **copy** of that class or template\n", 97 | "\n", 98 | "We decided that superman can fly and carry heavy stuff around like a real superman and in that way OOP helped us **model real life objects with code** so any object of that class has access to its *superpowers* " 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "### Class Methods\n", 106 | "\n", 107 | "Each class has its own methods which we used to call *functions*, they're the same thing but it's just because they're inside a class we refer to them as *methods* and we're going to look bit deeper into these methods and what's different about them \n", 108 | "\n", 109 | "Each method CAN'T have empty arguments, they all have a `self` argument as we've seen in the example and we can't ignore that argument because it enables us to access the variables defined within the class which are called *attributes* that each instance of any class has, in our example an object of the class `superman` has these attributes *name* , *age* and *job* which were initialized when we defined the object so in order for a method to access those you have to add the `self` argument just like how we did in our two methods `fly()` and `lift_heavy_stuff()`\n", 110 | "\n", 111 | "Let's create another class example which is a bit more interesting and fun and also uses other python concepts" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 9, 117 | "metadata": {}, 118 | "outputs": [ 119 | { 120 | "data": { 121 | "text/plain": [ 122 | "180" 123 | ] 124 | }, 125 | "execution_count": 9, 126 | "metadata": {}, 127 | "output_type": "execute_result" 128 | } 129 | ], 130 | "source": [ 131 | "class simp:\n", 132 | " def __init__(self,name,age,money):\n", 133 | " self.name = name\n", 134 | " self.age = age\n", 135 | " self.money = money\n", 136 | " self.girls = []\n", 137 | " \n", 138 | " def sub_to_girl(self,girl):\n", 139 | " self.girls.append(girl)\n", 140 | " self.money -= 20\n", 141 | " \n", 142 | " def show_money(self):\n", 143 | " return self.money\n", 144 | " \n", 145 | " def show_girls(self):\n", 146 | " return self.girls\n", 147 | " \n", 148 | "\n", 149 | "some_simp = simp('Brian',19,200)\n", 150 | "some_simp.sub_to_girl('Nicki')\n", 151 | "some_simp.show_money()" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": 10, 157 | "metadata": {}, 158 | "outputs": [ 159 | { 160 | "data": { 161 | "text/plain": [ 162 | "['Nicki']" 163 | ] 164 | }, 165 | "execution_count": 10, 166 | "metadata": {}, 167 | "output_type": "execute_result" 168 | } 169 | ], 170 | "source": [ 171 | "some_simp.show_girls()" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "### Example Explained\n", 179 | "\n", 180 | "Believe it or not, you have to be this silly sometimes just to understand some concepts easier :D\n", 181 | "So let's break this example down part by part\n", 182 | "\n", 183 | "1. The usual class definition and initialization\n", 184 | "2. in the `__init__()` method we have added an empty list this time which will be useful in the next method and also *money*, an integer value the user will provide\n", 185 | "3. `sub_to_girls()` takes two args, the usual `self` argument, as well as an arg the user provides so we then append it to our empty *girls* list\n", 186 | "4. In the same method we then subtract 20 from the money we already have " 187 | ] 188 | }, 189 | { 190 | "cell_type": "markdown", 191 | "metadata": {}, 192 | "source": [ 193 | "### Inheritance \n", 194 | "\n", 195 | "The concept of inheritance is a powerful and useful feature of OOP programming as it allows us to declare a *parent* class and then create *children* classes that inherit everything from that class including the attributes and methods \n", 196 | "\n", 197 | "Typically this is how it's structured \n", 198 | "\n", 199 | "```\n", 200 | " class parent:\n", 201 | " def __init__(self):\n", 202 | " #your attributes and methods here\n", 203 | " \n", 204 | " class child (parent):\n", 205 | " #your attributes and methods here\n", 206 | "\n", 207 | "```\n", 208 | "\n", 209 | "This way when we define an object of the child class we will be able to access the parent's class attributes and methods and we won't have to define a new `__init__()` method unless we want to add more attributes to the child class\n", 210 | "\n", 211 | "So by default adding the `__init__()` method to the child will overwrite the parent's method so i'll give two examples of how to declare a child class to inherit and also how to inherit the `__init__()` and add to it" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": 11, 217 | "metadata": {}, 218 | "outputs": [ 219 | { 220 | "name": "stdout", 221 | "output_type": "stream", 222 | "text": [ 223 | "Volvo\n" 224 | ] 225 | } 226 | ], 227 | "source": [ 228 | "class vehicle:\n", 229 | " def __init__(self):\n", 230 | " self.name = 'Volvo'\n", 231 | " self.color = 'white'\n", 232 | " self.is_new = True\n", 233 | " \n", 234 | " def accelerate(self,speed):\n", 235 | " return f\"{self.name} is now mvoing at speed of {speed}\"\n", 236 | "\n", 237 | "class car(vehicle):\n", 238 | " pass\n", 239 | "\n", 240 | "bmw = car() # Notice how i made an object of the child class just so we can see how we can access the parent's attributes\n", 241 | "\n", 242 | "print(bmw.name)" 243 | ] 244 | }, 245 | { 246 | "cell_type": "code", 247 | "execution_count": 12, 248 | "metadata": {}, 249 | "outputs": [ 250 | { 251 | "name": "stdout", 252 | "output_type": "stream", 253 | "text": [ 254 | "white\n" 255 | ] 256 | } 257 | ], 258 | "source": [ 259 | "print(bmw.color)" 260 | ] 261 | }, 262 | { 263 | "cell_type": "code", 264 | "execution_count": 13, 265 | "metadata": {}, 266 | "outputs": [ 267 | { 268 | "name": "stdout", 269 | "output_type": "stream", 270 | "text": [ 271 | "True\n" 272 | ] 273 | } 274 | ], 275 | "source": [ 276 | "print(bmw.is_new)" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": 14, 282 | "metadata": {}, 283 | "outputs": [ 284 | { 285 | "name": "stdout", 286 | "output_type": "stream", 287 | "text": [ 288 | "Volvo is now mvoing at speed of 200\n" 289 | ] 290 | } 291 | ], 292 | "source": [ 293 | "print(bmw.accelerate(200))" 294 | ] 295 | }, 296 | { 297 | "cell_type": "markdown", 298 | "metadata": {}, 299 | "source": [ 300 | "Now we're going to inherit the `__init__()` just so we can add more attributes to the child class" 301 | ] 302 | }, 303 | { 304 | "cell_type": "code", 305 | "execution_count": 4, 306 | "metadata": {}, 307 | "outputs": [ 308 | { 309 | "name": "stdout", 310 | "output_type": "stream", 311 | "text": [ 312 | "2018\n", 313 | "Volvo is now moving at speed of 100\n", 314 | "Volvo has stopped moving\n" 315 | ] 316 | } 317 | ], 318 | "source": [ 319 | "class vehicle:\n", 320 | " def __init__(self):\n", 321 | " self.name = 'Volvo'\n", 322 | " self.color = 'white'\n", 323 | " self.is_new = True\n", 324 | " \n", 325 | " def accelerate(self,speed):\n", 326 | " return f\"{self.name} is now moving at speed of {speed}\"\n", 327 | "\n", 328 | "class car(vehicle):\n", 329 | " def __init__(self):\n", 330 | " super().__init__()\n", 331 | " self.model = 2018\n", 332 | " \n", 333 | " def stop(self):\n", 334 | " return f\"{self.name} has stopped moving\"\n", 335 | "\n", 336 | " \n", 337 | "van = car()\n", 338 | "print(van.model)\n", 339 | "print(van.accelerate(100))\n", 340 | "print(van.stop())" 341 | ] 342 | }, 343 | { 344 | "cell_type": "markdown", 345 | "metadata": {}, 346 | "source": [ 347 | "### Example review\n", 348 | "\n", 349 | "So you're probably wondering what is this `super()` method and what did it add to the code so please stay with me\n", 350 | "Remember when i mentioned earlier that defining a new `__init__()` will overwrite the parent's one? Well it'd be a problem if we did so for that reason we used this `super()` method to inherit the `__init__()` method of the parent and this method automatically figures out which `__init__()` are we talking about in case of multiple classes because it sees which parent class our child class inherited from\n", 351 | "After we inherited the `__init__()` method which is a default behavior by the way as we saw in the first example, we added a new attribute to the child clas which is the `self.model` \n", 352 | "So in short *we use the `super()` method to inherit the parent's `__init__()` method because defining a new one for the child will overwrite the parent's one and so we can add more attributes to the child `__init__()` method*" 353 | ] 354 | }, 355 | { 356 | "cell_type": "markdown", 357 | "metadata": {}, 358 | "source": [ 359 | "### Class Variables\n", 360 | "\n", 361 | "Sometimes we need to have default values for some classes and this is done by assigning *class variables* to do that task and they're pretty simple to implement just like in this example" 362 | ] 363 | }, 364 | { 365 | "cell_type": "code", 366 | "execution_count": 16, 367 | "metadata": {}, 368 | "outputs": [ 369 | { 370 | "name": "stdout", 371 | "output_type": "stream", 372 | "text": [ 373 | "John\n", 374 | "33\n", 375 | "Project manager\n", 376 | "2000\n" 377 | ] 378 | } 379 | ], 380 | "source": [ 381 | "class employee:\n", 382 | " name = 'John'\n", 383 | " age = 33\n", 384 | " position = 'Project manager'\n", 385 | " salary = 2000\n", 386 | " def __init__(self):\n", 387 | " pass\n", 388 | "\n", 389 | "emp = employee()\n", 390 | "print(emp.name)\n", 391 | "print(emp.age)\n", 392 | "print(emp.position)\n", 393 | "print(emp.salary)" 394 | ] 395 | }, 396 | { 397 | "cell_type": "markdown", 398 | "metadata": {}, 399 | "source": [ 400 | "In the example above we didn't have to pass any args to the `__init__()` method since we explicitly declared our attributes that way so any objects of that class have access to them and we can overwrite those variables easily through the `__init__()` method this way " 401 | ] 402 | }, 403 | { 404 | "cell_type": "code", 405 | "execution_count": 17, 406 | "metadata": {}, 407 | "outputs": [ 408 | { 409 | "name": "stdout", 410 | "output_type": "stream", 411 | "text": [ 412 | "Robert\n", 413 | "33\n", 414 | "Project manager\n", 415 | "2500\n" 416 | ] 417 | } 418 | ], 419 | "source": [ 420 | "class employee:\n", 421 | " name = 'John'\n", 422 | " age = 33\n", 423 | " position = 'Project manager'\n", 424 | " salary = 2000\n", 425 | " def __init__(self,name,salary): #YOU CAN PASS IN ANY ARGS YOU WANT EVEN IF YOU PASS MORE NEW ARGS\n", 426 | " self.name = name\n", 427 | " self.salary = salary\n", 428 | "\n", 429 | "emp = employee('Robert',2500)\n", 430 | "print(emp.name)\n", 431 | "print(emp.age)\n", 432 | "print(emp.position)\n", 433 | "print(emp.salary)" 434 | ] 435 | }, 436 | { 437 | "cell_type": "markdown", 438 | "metadata": {}, 439 | "source": [ 440 | "### Polymorphism\n", 441 | "\n", 442 | "Polymorphism allows us to assign same name to different class methods or functions and in this section we're only gonna be concenred with class methods \n", 443 | "\n", 444 | "So the way we will implement this concept is we're gonna define two classes with the same class methods names but different class method bodies and we're gonna see how to assign objects and how do these class methods behave differently for each object\n" 445 | ] 446 | }, 447 | { 448 | "cell_type": "code", 449 | "execution_count": 5, 450 | "metadata": {}, 451 | "outputs": [ 452 | { 453 | "name": "stdout", 454 | "output_type": "stream", 455 | "text": [ 456 | "New Delhi\n", 457 | "Hindi and English\n", 458 | "Washington, D.C.\n", 459 | "English\n" 460 | ] 461 | } 462 | ], 463 | "source": [ 464 | "class India():\n", 465 | " def capital(self):\n", 466 | " print(\"New Delhi\")\n", 467 | " \n", 468 | " def language(self):\n", 469 | " print(\"Hindi and English\")\n", 470 | "\n", 471 | " \n", 472 | "class USA():\n", 473 | " def capital(self):\n", 474 | " print(\"Washington, D.C.\")\n", 475 | " \n", 476 | " def language(self):\n", 477 | " print(\"English\") \n", 478 | "\n", 479 | "\n", 480 | "obj_ind = India()\n", 481 | "obj_usa = USA()\n", 482 | "for country in (obj_ind, obj_usa):\n", 483 | " country.capital()\n", 484 | " country.language()" 485 | ] 486 | }, 487 | { 488 | "cell_type": "markdown", 489 | "metadata": {}, 490 | "source": [ 491 | "Also the same can be applied to inheritence in python, we'll see how to implement polymorphism with classes inheriting from each other " 492 | ] 493 | }, 494 | { 495 | "cell_type": "code", 496 | "execution_count": 6, 497 | "metadata": {}, 498 | "outputs": [ 499 | { 500 | "name": "stdout", 501 | "output_type": "stream", 502 | "text": [ 503 | "There are different types of birds\n", 504 | "Most of the birds can fly but some cannot\n", 505 | "There are different types of birds\n", 506 | "Parrots can fly\n", 507 | "There are different types of birds\n", 508 | "Penguins do not fly\n" 509 | ] 510 | } 511 | ], 512 | "source": [ 513 | "class Bird:\n", 514 | " def intro(self):\n", 515 | " print(\"There are different types of birds\")\n", 516 | " \n", 517 | " def flight(self):\n", 518 | " print(\"Most of the birds can fly but some cannot\")\n", 519 | "\n", 520 | "class parrot(Bird):\n", 521 | " def flight(self):\n", 522 | " print(\"Parrots can fly\")\n", 523 | " \n", 524 | "class penguin(Bird):\n", 525 | " def flight(self):\n", 526 | " print(\"Penguins do not fly\")\n", 527 | " \n", 528 | "obj_bird = Bird()\n", 529 | "obj_parr = parrot()\n", 530 | "obj_peng = penguin()\n", 531 | " \n", 532 | "obj_bird.intro()\n", 533 | "obj_bird.flight()\n", 534 | " \n", 535 | "obj_parr.intro()\n", 536 | "obj_parr.flight()\n", 537 | " \n", 538 | "obj_peng.intro()\n", 539 | "obj_peng.flight()" 540 | ] 541 | }, 542 | { 543 | "cell_type": "markdown", 544 | "metadata": {}, 545 | "source": [ 546 | "### Encapsulation\n", 547 | "\n", 548 | "The idea of encapsulation is the ability to define and use variables only within the scope of the class, which means we can only access them inside the class methods we could say but not directly from outside the class\n", 549 | "\n", 550 | "By convention, when declaring such variables we use a single underscore prior to the variable name `self._name` for example but in reality that has no effect on *making the variables private* therefore we use double underscore as prefix to achieve such task \n", 551 | "\n", 552 | "These two examples will showcase both options so we can see why we choose one over the other for the sake of encapsulation " 553 | ] 554 | }, 555 | { 556 | "cell_type": "code", 557 | "execution_count": 3, 558 | "metadata": {}, 559 | "outputs": [ 560 | { 561 | "name": "stdout", 562 | "output_type": "stream", 563 | "text": [ 564 | "Dev\n", 565 | "30\n", 566 | "Dev\n", 567 | "30\n" 568 | ] 569 | } 570 | ], 571 | "source": [ 572 | "# USING SINGLE UNDERSCORE TO LIMIT THE VARIABLES ACCESS\n", 573 | "\n", 574 | "class Person:\n", 575 | " def __init__(self, name, age=0):\n", 576 | " self.name = name\n", 577 | " self._age = age\n", 578 | " \n", 579 | " def display(self):\n", 580 | " print(self.name)\n", 581 | " print(self._age)\n", 582 | " \n", 583 | "person = Person('Dev', 30)\n", 584 | "#accessing using class method\n", 585 | "person.display()\n", 586 | "#accessing directly from outside\n", 587 | "print(person.name)\n", 588 | "print(person._age)" 589 | ] 590 | }, 591 | { 592 | "cell_type": "code", 593 | "execution_count": 4, 594 | "metadata": {}, 595 | "outputs": [ 596 | { 597 | "name": "stdout", 598 | "output_type": "stream", 599 | "text": [ 600 | "Dev\n", 601 | "30\n", 602 | "Trying to access variables from outside the class \n", 603 | "Dev\n" 604 | ] 605 | }, 606 | { 607 | "ename": "AttributeError", 608 | "evalue": "'Person' object has no attribute '__age'", 609 | "output_type": "error", 610 | "traceback": [ 611 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 612 | "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", 613 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 14\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Trying to access variables from outside the class '\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 15\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mperson\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mname\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 16\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mperson\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__age\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 614 | "\u001b[1;31mAttributeError\u001b[0m: 'Person' object has no attribute '__age'" 615 | ] 616 | } 617 | ], 618 | "source": [ 619 | "class Person:\n", 620 | " def __init__(self, name, age=0):\n", 621 | " self.name = name\n", 622 | " self.__age = age\n", 623 | " \n", 624 | " def display(self):\n", 625 | " print(self.name)\n", 626 | " print(self.__age)\n", 627 | " \n", 628 | "person = Person('Dev', 30)\n", 629 | "#accessing using class method\n", 630 | "person.display()\n", 631 | "#accessing directly from outside\n", 632 | "print('Trying to access variables from outside the class ')\n", 633 | "print(person.name)\n", 634 | "print(person.__age) # THIS ATTRIBUTE ONLY EXISTS WITHIN THE SCOPE OF THE CLASS ONLY THAT'S WHY WE CAN'T ACCESS IT FROM OUTSIDE" 635 | ] 636 | } 637 | ], 638 | "metadata": { 639 | "kernelspec": { 640 | "display_name": "Python 3", 641 | "language": "python", 642 | "name": "python3" 643 | }, 644 | "language_info": { 645 | "codemirror_mode": { 646 | "name": "ipython", 647 | "version": 3 648 | }, 649 | "file_extension": ".py", 650 | "mimetype": "text/x-python", 651 | "name": "python", 652 | "nbconvert_exporter": "python", 653 | "pygments_lexer": "ipython3", 654 | "version": "3.8.3" 655 | } 656 | }, 657 | "nbformat": 4, 658 | "nbformat_minor": 4 659 | } 660 | -------------------------------------------------------------------------------- /Python-Notebooks/employee.csv: -------------------------------------------------------------------------------- 1 | Sabrina,9567622648,IT support 2 | John,9456721352,Sysadmin 3 | Kelly,9645871235,Receptionist 4 | -------------------------------------------------------------------------------- /Python-Notebooks/requirements.txt: -------------------------------------------------------------------------------- 1 | argon2-cffi==20.1.0 2 | async-generator==1.10 3 | attrs==20.2.0 4 | backcall==0.2.0 5 | bleach==3.1.5 6 | cffi==1.14.2 7 | colorama==0.4.3 8 | decorator==4.4.2 9 | defusedxml==0.6.0 10 | entrypoints==0.3 11 | ipykernel==5.3.4 12 | ipython==7.18.1 13 | ipython-genutils==0.2.0 14 | ipywidgets==7.5.1 15 | jedi==0.17.2 16 | Jinja2==2.11.2 17 | jsonschema==3.2.0 18 | jupyter==1.0.0 19 | jupyter-client==6.1.7 20 | jupyter-console==6.2.0 21 | jupyter-core==4.6.3 22 | jupyterlab-pygments==0.1.1 23 | MarkupSafe==1.1.1 24 | mistune==0.8.4 25 | nbclient==0.5.0 26 | nbconvert==6.0.1 27 | nbformat==5.0.7 28 | nest-asyncio==1.4.0 29 | notebook==6.1.4 30 | packaging==20.4 31 | pandocfilters==1.4.2 32 | parso==0.7.1 33 | pickleshare==0.7.5 34 | prometheus-client==0.8.0 35 | prompt-toolkit==3.0.7 36 | pycparser==2.20 37 | Pygments==2.6.1 38 | pyparsing==2.4.7 39 | pyrsistent==0.16.0 40 | python-dateutil==2.8.1 41 | pywin32==228 42 | pywinpty==0.5.7 43 | pyzmq==19.0.2 44 | qtconsole==4.7.7 45 | QtPy==1.9.0 46 | Send2Trash==1.5.0 47 | six==1.15.0 48 | terminado==0.8.3 49 | testpath==0.4.4 50 | tornado==6.0.4 51 | traitlets==5.0.4 52 | wcwidth==0.2.5 53 | webencodings==0.5.1 54 | widgetsnbextension==3.5.1 55 | -------------------------------------------------------------------------------- /Python-Notebooks/software.csv: -------------------------------------------------------------------------------- 1 | name,version,users 2 | Chatty Chicken,1.02.03,54 3 | Coder Kitchen,1.32.30,104 4 | Sensible Writer,4.1.03,454 5 | Magic Image Viewer,0.1.20,4 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Byte-Sized-Code 2 | A collection of resources for learning Python from the ground up. 3 | 4 | ## How to use/run the Notebooks 5 | 6 | As suggested by [u/ko773](https://www.reddit.com/r/learnprogramming/comments/iv1aer/looking_to_learn_python/g5qui07/?context=3) on reddit, you can use [Google Colab](colab.research.google.com 7 | ) to view the notebooks online. Here is an in-depth video guide on how to do it: 8 | 9 | [![Demo CountPages alpha](https://j.gifs.com/3QAwvp.gif)](https://www.youtube.com/watch?v=B3pHRc0MWYE&ab_channel=ByteSizedCode) 10 | 11 | Have a look [here](https://github.com/aceking007/Byte-Sized-Code/blob/master/LOCAL_USE.md) to know more about how to run the jupyter notebooks on a local machine. 12 | 13 | ## Python notebooks 14 | 15 | Feel free to use the notebooks as a cheat-sheet or to learn more about python. 16 | Feel free to open an issue (or even better, send a Pull Request) for any changes. 17 | Have a look [here](https://github.com/aceking007/Byte-Sized-Code/blob/master/CONTRIBUTING.md) before contributing, to make your pull request more likely to be merged. 18 | 19 | 20 | ## Checklist 21 | Things to do: 22 | - [x] ~~Basic Python Syntax~~ 23 | - [x] ~~Loops and Recursion~~ 24 | - [x] ~~Strings, Lists, and Dictionaries~~ 25 | - [x] ~~Working with Files and Directories~~ 26 | - [x] ~~Working with CSV Files~~ 27 | - [x] ~~Regular Expressions~~ 28 | - [ ] OOPS in Python 29 | - [ ] Numpy cheat sheet 30 | - [ ] Pandas cheat sheet 31 | 32 | ## Projects 33 | 34 | Feel free to add some beginner-friendly projects to the projects directory of the repository. 35 | Here is a checklist to get things started: 36 | 37 | ## Checklist 38 | Projects to add: 39 | - [x] ~~Caesar Cipher~~ 40 | - [ ] Joke Telling Program 41 | - [ ] Mad Libs Generator 42 | - [ ] Dice Rolling Simulator 43 | - [ ] Guess the Number 44 | - [ ] Hangman 45 | 46 | --------------------------------------------------------------------------------