├── .gitignore ├── README.md ├── notebooks ├── 01_zip_function.ipynb ├── 02_zip_longest_function.ipynb ├── 03_enumerate.ipynb ├── 04_lambda.ipynb ├── 05_sort.ipynb ├── 06_map.ipynb ├── 07_filter.ipynb ├── 08_iterators.ipynb ├── 09_generators.ipynb ├── 10_any_all.ipynb ├── 11_closures.ipynb ├── 12_args_kwargs.ipynb ├── 13_decorators.ipynb ├── 14_chaining_decorators.ipynb ├── 15_property.ipynb ├── 16_classmethod.ipynb ├── 17_staticmethod.ipynb ├── 18_reduce.ipynb ├── 19_accumulate.ipynb ├── 20_get_dictionary.ipynb ├── 21_counter.ipynb ├── 22_sets.ipynb ├── 23_set_operations.ipynb ├── 24_frozenset.ipynb ├── 25_files_you_must_have.ipynb ├── 26_python-dotenv.ipynb ├── 27_custom_exceptions.ipynb ├── 28_unit_testing.ipynb ├── 29_fixtures.ipynb └── 30_parametrized_tests.ipynb ├── python.jpg └── solutions ├── solution_anagrams.ipynb ├── solution_anagrams.py ├── solution_bank_accounts.ipynb ├── solution_bank_accounts.py ├── solution_complement_of_a_set.ipynb ├── solution_complement_of_a_set.py ├── solution_fibonacci_numbers.ipynb ├── solution_fibonacci_numbers.py ├── solution_grouping_the_elements_by_the_count.ipynb ├── solution_grouping_the_elements_by_the_count.py ├── solution_have_you_seen_this_number_before.ipynb ├── solution_have_you_seen_this_number_before.py ├── solution_implementing_xor.ipynb ├── solution_implementing_xor.py ├── solution_learning_the_words_in_a_strange_order.ipynb ├── solution_learning_the_words_in_a_strange_order.py ├── solution_prime_numbers.ipynb ├── solution_prime_numbers.py ├── solution_summing_numbers_like_in_school.ipynb ├── solution_summing_numbers_like_in_school.py ├── solution_transforming_data.ipynb └── solution_transforming_data.py /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints 2 | vs-code-files -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advanced Python Skills Course 2 | 3 | ![Python](python.jpg) 4 | 5 | Welcome to the [Advanced Python Skills](https://www.udemy.com/course/advanced-python-skills-become-a-better-python-developer/) course. 6 | 7 | This a course hosted by David Armendáriz in Udemy. 8 | 9 | In this repo, you will find all the scripts that I coded in the video lectures so you can have them! 10 | 11 | Enjoy the course and if you have any questions, don't hesitate to contact me in [Math as a Second Language Discord Server](https://discord.gg/ej2F3Qj) 12 | -------------------------------------------------------------------------------- /notebooks/01_zip_function.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #1\n", 8 | "## The zip function\n", 9 | "\n", 10 | "* Takes iterables (lists, dictionaries, tuples, strings, etc.) and \"zips\" them into tuples.\n", 11 | "* Is used for parallel iteration\n", 12 | "* Returns a `zip` object, which is an iterator of tuples" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "## Lists" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 80, 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "countries = [\"Ecuador\", \"Perú\", \"Colombia\", \"USA\", \"Chile\"]\n", 29 | "capitals = [\"Quito\", \"Lima\", \"Bogotá\", \"Washington DC\", \"Santiago\"]\n", 30 | "cities = [\"Guayaquil\", \"Trujillo\", \"Medellín\", \"New York\", \"Valparaíso\"]\n", 31 | "countries_and_capitals = zip(countries, capitals, cities)" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 81, 37 | "metadata": {}, 38 | "outputs": [ 39 | { 40 | "data": { 41 | "text/plain": [ 42 | "[('Ecuador', 'Quito', 'Guayaquil'),\n", 43 | " ('Perú', 'Lima', 'Trujillo'),\n", 44 | " ('Colombia', 'Bogotá', 'Medellín'),\n", 45 | " ('USA', 'Washington DC', 'New York'),\n", 46 | " ('Chile', 'Santiago', 'Valparaíso')]" 47 | ] 48 | }, 49 | "execution_count": 81, 50 | "metadata": {}, 51 | "output_type": "execute_result" 52 | } 53 | ], 54 | "source": [ 55 | "list(countries_and_capitals)" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "## Dictionaries" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 87, 68 | "metadata": {}, 69 | "outputs": [], 70 | "source": [ 71 | "products = {\"apple\": 0.5, \"pineapple\": 0.7}\n", 72 | "tech_products = {\"iPhone\": 1000, \"Windows\": 600}\n", 73 | "products_and_tech_products = zip(products.values(), tech_products)" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 88, 79 | "metadata": {}, 80 | "outputs": [ 81 | { 82 | "data": { 83 | "text/plain": [ 84 | "[(0.5, 'iPhone'), (0.7, 'Windows')]" 85 | ] 86 | }, 87 | "execution_count": 88, 88 | "metadata": {}, 89 | "output_type": "execute_result" 90 | } 91 | ], 92 | "source": [ 93 | "list(products_and_tech_products)" 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [ 100 | "## Tuples" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": 89, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "countries = (\"Ecuador\", \"Perú\", \"Colombia\", \"USA\", \"Chile\")\n", 110 | "capitals = (\"Quito\", \"Lima\", \"Bogotá\", \"Washington DC\", \"Santiago\")\n", 111 | "cities = (\"Guayaquil\", \"Trujillo\", \"Medellín\", \"New York\", \"Valparaíso\")\n", 112 | "countries_and_capitals = zip(countries, capitals, cities)" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": 90, 118 | "metadata": {}, 119 | "outputs": [ 120 | { 121 | "data": { 122 | "text/plain": [ 123 | "[('Ecuador', 'Quito', 'Guayaquil'),\n", 124 | " ('Perú', 'Lima', 'Trujillo'),\n", 125 | " ('Colombia', 'Bogotá', 'Medellín'),\n", 126 | " ('USA', 'Washington DC', 'New York'),\n", 127 | " ('Chile', 'Santiago', 'Valparaíso')]" 128 | ] 129 | }, 130 | "execution_count": 90, 131 | "metadata": {}, 132 | "output_type": "execute_result" 133 | } 134 | ], 135 | "source": [ 136 | "list(countries_and_capitals)" 137 | ] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": {}, 142 | "source": [ 143 | "## Strings" 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": 91, 149 | "metadata": {}, 150 | "outputs": [], 151 | "source": [ 152 | "country = \"Ecuador\"\n", 153 | "capital = \"Quito\"\n", 154 | "country_and_capital = zip(country, capital)" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": 93, 160 | "metadata": {}, 161 | "outputs": [ 162 | { 163 | "data": { 164 | "text/plain": [ 165 | "[('E', 'Q'), ('c', 'u'), ('u', 'i'), ('a', 't'), ('d', 'o')]" 166 | ] 167 | }, 168 | "execution_count": 93, 169 | "metadata": {}, 170 | "output_type": "execute_result" 171 | } 172 | ], 173 | "source": [ 174 | "list(country_and_capital)" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": null, 180 | "metadata": {}, 181 | "outputs": [], 182 | "source": [] 183 | } 184 | ], 185 | "metadata": { 186 | "kernelspec": { 187 | "display_name": "Python 3", 188 | "language": "python", 189 | "name": "python3" 190 | }, 191 | "language_info": { 192 | "codemirror_mode": { 193 | "name": "ipython", 194 | "version": 3 195 | }, 196 | "file_extension": ".py", 197 | "mimetype": "text/x-python", 198 | "name": "python", 199 | "nbconvert_exporter": "python", 200 | "pygments_lexer": "ipython3", 201 | "version": "3.6.9" 202 | } 203 | }, 204 | "nbformat": 4, 205 | "nbformat_minor": 4 206 | } 207 | -------------------------------------------------------------------------------- /notebooks/02_zip_longest_function.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #2\n", 8 | "## The zip_longest function\n", 9 | "\n", 10 | "* Similar to the zip function\n", 11 | "* Takes into account the longest iterable passed." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Lists" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 12, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "from itertools import zip_longest" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 18, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "countries = [\"Ecuador\", \"Perú\", \"Colombia\", \"USA\", \"Chile\"]\n", 37 | "capitals = [\"Quito\", \"Lima\", \"Bogotá\", \"Washington DC\"]\n", 38 | "cities = [\"Guayaquil\", \"Trujillo\", \"Medellín\", \"New York\"]\n", 39 | "countries_and_capitals = zip_longest(countries, capitals, cities, fillvalue=\"Valparaíso\")" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 19, 45 | "metadata": {}, 46 | "outputs": [ 47 | { 48 | "data": { 49 | "text/plain": [ 50 | "[('Ecuador', 'Quito', 'Guayaquil'),\n", 51 | " ('Perú', 'Lima', 'Trujillo'),\n", 52 | " ('Colombia', 'Bogotá', 'Medellín'),\n", 53 | " ('USA', 'Washington DC', 'New York'),\n", 54 | " ('Chile', 'Valparaíso', 'Valparaíso')]" 55 | ] 56 | }, 57 | "execution_count": 19, 58 | "metadata": {}, 59 | "output_type": "execute_result" 60 | } 61 | ], 62 | "source": [ 63 | "list(countries_and_capitals)" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": null, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [] 72 | } 73 | ], 74 | "metadata": { 75 | "kernelspec": { 76 | "display_name": "Python 3", 77 | "language": "python", 78 | "name": "python3" 79 | }, 80 | "language_info": { 81 | "codemirror_mode": { 82 | "name": "ipython", 83 | "version": 3 84 | }, 85 | "file_extension": ".py", 86 | "mimetype": "text/x-python", 87 | "name": "python", 88 | "nbconvert_exporter": "python", 89 | "pygments_lexer": "ipython3", 90 | "version": "3.6.9" 91 | } 92 | }, 93 | "nbformat": 4, 94 | "nbformat_minor": 4 95 | } 96 | -------------------------------------------------------------------------------- /notebooks/03_enumerate.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #3\n", 8 | "## The enumerate function\n", 9 | "\n", 10 | "* Adds a counter to an iterable and returns it as an enumerate object.\n", 11 | "* The enumerate object is usually used in for loops." 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 14, 17 | "metadata": {}, 18 | "outputs": [ 19 | { 20 | "name": "stdout", 21 | "output_type": "stream", 22 | "text": [ 23 | "[(0, 'apple'), (1, 'pineapple'), (2, 'lemon'), (3, 'watermelon'), (4, 'grapes')]\n" 24 | ] 25 | } 26 | ], 27 | "source": [ 28 | "fruits = [\"apple\", \"pineapple\", \"lemon\", \"watermelon\", \"grapes\"]\n", 29 | "enumerated_fruits = enumerate(fruits)\n", 30 | "print(list(enumerated_fruits))" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 16, 36 | "metadata": {}, 37 | "outputs": [ 38 | { 39 | "name": "stdout", 40 | "output_type": "stream", 41 | "text": [ 42 | "file1.jpg\n", 43 | "file2.jpg\n", 44 | "file3.jpg\n", 45 | "file4.jpg\n", 46 | "file5.jpg\n" 47 | ] 48 | } 49 | ], 50 | "source": [ 51 | "for index, element in enumerate(fruits, start=1):\n", 52 | " filename = f\"file{index}.jpg\"\n", 53 | " # do something with the file and the element\n", 54 | " print(filename)" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": null, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [] 63 | } 64 | ], 65 | "metadata": { 66 | "kernelspec": { 67 | "display_name": "Python 3", 68 | "language": "python", 69 | "name": "python3" 70 | }, 71 | "language_info": { 72 | "codemirror_mode": { 73 | "name": "ipython", 74 | "version": 3 75 | }, 76 | "file_extension": ".py", 77 | "mimetype": "text/x-python", 78 | "name": "python", 79 | "nbconvert_exporter": "python", 80 | "pygments_lexer": "ipython3", 81 | "version": "3.6.9" 82 | } 83 | }, 84 | "nbformat": 4, 85 | "nbformat_minor": 4 86 | } 87 | -------------------------------------------------------------------------------- /notebooks/04_lambda.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #4\n", 8 | "## Lambda functions\n", 9 | "\n", 10 | "* Also called anonymous functions because they are unnamed.\n", 11 | "* Its syntax is: **lambda arguments: expression**\n", 12 | "* They can take any number of parameters.\n", 13 | "* They are useful to understand the following videos, so pay close attention!" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 21, 19 | "metadata": {}, 20 | "outputs": [ 21 | { 22 | "name": "stdout", 23 | "output_type": "stream", 24 | "text": [ 25 | "12\n" 26 | ] 27 | } 28 | ], 29 | "source": [ 30 | "i = 5\n", 31 | "add = lambda x: x+i\n", 32 | "print(add(7))" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 22, 38 | "metadata": {}, 39 | "outputs": [], 40 | "source": [ 41 | "lambda_functions = [lambda x: x+j for j in range(3)]" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 23, 47 | "metadata": {}, 48 | "outputs": [ 49 | { 50 | "name": "stdout", 51 | "output_type": "stream", 52 | "text": [ 53 | "7\n" 54 | ] 55 | } 56 | ], 57 | "source": [ 58 | "# the first element of this list should be lambda x: x+0\n", 59 | "first_lambda_function = lambda_functions[0]\n", 60 | "print(first_lambda_function(5))" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": 27, 66 | "metadata": {}, 67 | "outputs": [], 68 | "source": [ 69 | "multiplication = lambda a,b,c: a*b*c" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": 28, 75 | "metadata": {}, 76 | "outputs": [ 77 | { 78 | "data": { 79 | "text/plain": [ 80 | "40" 81 | ] 82 | }, 83 | "execution_count": 28, 84 | "metadata": {}, 85 | "output_type": "execute_result" 86 | } 87 | ], 88 | "source": [ 89 | "multiplication(4,5,2)" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": null, 95 | "metadata": {}, 96 | "outputs": [], 97 | "source": [] 98 | } 99 | ], 100 | "metadata": { 101 | "kernelspec": { 102 | "display_name": "Python 3", 103 | "language": "python", 104 | "name": "python3" 105 | }, 106 | "language_info": { 107 | "codemirror_mode": { 108 | "name": "ipython", 109 | "version": 3 110 | }, 111 | "file_extension": ".py", 112 | "mimetype": "text/x-python", 113 | "name": "python", 114 | "nbconvert_exporter": "python", 115 | "pygments_lexer": "ipython3", 116 | "version": "3.6.9" 117 | } 118 | }, 119 | "nbformat": 4, 120 | "nbformat_minor": 4 121 | } 122 | -------------------------------------------------------------------------------- /notebooks/05_sort.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #5\n", 8 | "## Sort vs Sorted\n", 9 | "\n", 10 | "* The `sort` method only works for lists.\n", 11 | "* The `sorted` function works for any iterable.\n", 12 | "* You can specify the parameter `reverse` in both of them.\n", 13 | "* And you can also specify a key." 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 38, 19 | "metadata": {}, 20 | "outputs": [], 21 | "source": [ 22 | "fruits = {\"apple\": 40, \"watermelon\": 50, \"pineapple\":10, \"grapes\":15}" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 42, 28 | "metadata": {}, 29 | "outputs": [ 30 | { 31 | "data": { 32 | "text/plain": [ 33 | "['apple', 'grapes', 'pineapple', 'watermelon']" 34 | ] 35 | }, 36 | "execution_count": 42, 37 | "metadata": {}, 38 | "output_type": "execute_result" 39 | } 40 | ], 41 | "source": [ 42 | "sorted(fruits)" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 44, 48 | "metadata": {}, 49 | "outputs": [ 50 | { 51 | "data": { 52 | "text/plain": [ 53 | "['pineapple', 'grapes', 'apple', 'watermelon']" 54 | ] 55 | }, 56 | "execution_count": 44, 57 | "metadata": {}, 58 | "output_type": "execute_result" 59 | } 60 | ], 61 | "source": [ 62 | "sorted(fruits, key=lambda fruit: fruits[fruit])" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "metadata": {}, 69 | "outputs": [], 70 | "source": [] 71 | } 72 | ], 73 | "metadata": { 74 | "kernelspec": { 75 | "display_name": "Python 3", 76 | "language": "python", 77 | "name": "python3" 78 | }, 79 | "language_info": { 80 | "codemirror_mode": { 81 | "name": "ipython", 82 | "version": 3 83 | }, 84 | "file_extension": ".py", 85 | "mimetype": "text/x-python", 86 | "name": "python", 87 | "nbconvert_exporter": "python", 88 | "pygments_lexer": "ipython3", 89 | "version": "3.6.9" 90 | } 91 | }, 92 | "nbformat": 4, 93 | "nbformat_minor": 4 94 | } 95 | -------------------------------------------------------------------------------- /notebooks/06_map.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #6\n", 8 | "## The map function\n", 9 | "\n", 10 | "* Applies a given function to each item of an iterable.\n", 11 | "* Returns a map object (which is an iterator).\n", 12 | "* Use it instead of loops whenever you can!" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "**Example:** Capitalize all the strings of a list" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 46, 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "fruits = [\"apple\", \"watermelon\", \"pineapple\", \"grapes\"]" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": 47, 34 | "metadata": {}, 35 | "outputs": [ 36 | { 37 | "name": "stdout", 38 | "output_type": "stream", 39 | "text": [ 40 | "['Apple', 'Watermelon', 'Pineapple', 'Grapes']\n" 41 | ] 42 | } 43 | ], 44 | "source": [ 45 | "result = list()\n", 46 | "for fruit in fruits:\n", 47 | " result.append(fruit.capitalize())\n", 48 | "print(result)" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 55, 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "def process(fruit):\n", 58 | " resulting_string = fruit.capitalize()\n", 59 | " if fruit.endswith(\"s\"):\n", 60 | " resulting_string += \" are great!\"\n", 61 | " else:\n", 62 | " resulting_string += \" is great!\"\n", 63 | " return resulting_string" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 56, 69 | "metadata": {}, 70 | "outputs": [ 71 | { 72 | "name": "stdout", 73 | "output_type": "stream", 74 | "text": [ 75 | "['Apple is great!', 'Watermelon is great!', 'Pineapple is great!', 'Grapes are great!']\n" 76 | ] 77 | } 78 | ], 79 | "source": [ 80 | "result = map(process, fruits)\n", 81 | "print(list(result))" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": null, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [] 90 | } 91 | ], 92 | "metadata": { 93 | "kernelspec": { 94 | "display_name": "Python 3", 95 | "language": "python", 96 | "name": "python3" 97 | }, 98 | "language_info": { 99 | "codemirror_mode": { 100 | "name": "ipython", 101 | "version": 3 102 | }, 103 | "file_extension": ".py", 104 | "mimetype": "text/x-python", 105 | "name": "python", 106 | "nbconvert_exporter": "python", 107 | "pygments_lexer": "ipython3", 108 | "version": "3.6.9" 109 | } 110 | }, 111 | "nbformat": 4, 112 | "nbformat_minor": 4 113 | } 114 | -------------------------------------------------------------------------------- /notebooks/07_filter.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #7\n", 8 | "## The filter function\n", 9 | "\n", 10 | "* Constructs an iterator from elements of an iterable for which a function returns True.\n", 11 | "* In other words: it filters an iterable based on a condition given by a function." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "**Example:** Filter a list of strings based on the condition that it starts with the letter \"a\"" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 5, 24 | "metadata": {}, 25 | "outputs": [ 26 | { 27 | "name": "stdout", 28 | "output_type": "stream", 29 | "text": [ 30 | "\n" 31 | ] 32 | } 33 | ], 34 | "source": [ 35 | "fruits = [\"apple\", \"avocado\", \"watermelon\", \"grapes\"]\n", 36 | "filtered_fruits = filter(lambda fruit: fruit.startswith(\"a\") == True, fruits)\n", 37 | "print(filtered_fruits)" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 6, 43 | "metadata": {}, 44 | "outputs": [ 45 | { 46 | "data": { 47 | "text/plain": [ 48 | "['apple', 'avocado']" 49 | ] 50 | }, 51 | "execution_count": 6, 52 | "metadata": {}, 53 | "output_type": "execute_result" 54 | } 55 | ], 56 | "source": [ 57 | "list(filtered_fruits)" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": {}, 63 | "source": [ 64 | "**Example**: Filter a dictionary based on the condition that the value must be greater than some number" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 14, 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "fruits = {\"apple\": 60, \"avocado\": 40, \"watermelon\": 15, \"grapes\": 200}\n", 74 | "filtered_fruits = filter(lambda t: t[1] > 50, fruits.items())" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 15, 80 | "metadata": {}, 81 | "outputs": [], 82 | "source": [ 83 | "fruits_filtered_dictionary = dict(filtered_fruits)" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 16, 89 | "metadata": {}, 90 | "outputs": [ 91 | { 92 | "data": { 93 | "text/plain": [ 94 | "{'apple': 60, 'grapes': 200}" 95 | ] 96 | }, 97 | "execution_count": 16, 98 | "metadata": {}, 99 | "output_type": "execute_result" 100 | } 101 | ], 102 | "source": [ 103 | "fruits_filtered_dictionary" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": null, 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [] 112 | } 113 | ], 114 | "metadata": { 115 | "kernelspec": { 116 | "display_name": "Python 3", 117 | "language": "python", 118 | "name": "python3" 119 | }, 120 | "language_info": { 121 | "codemirror_mode": { 122 | "name": "ipython", 123 | "version": 3 124 | }, 125 | "file_extension": ".py", 126 | "mimetype": "text/x-python", 127 | "name": "python", 128 | "nbconvert_exporter": "python", 129 | "pygments_lexer": "ipython3", 130 | "version": "3.6.9" 131 | } 132 | }, 133 | "nbformat": 4, 134 | "nbformat_minor": 4 135 | } 136 | -------------------------------------------------------------------------------- /notebooks/08_iterators.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #8\n", 8 | "\n", 9 | "## Iterables vs Iterators\n", 10 | "\n", 11 | "* So far we have used these two words a lot, and maybe I have use it interchangeably, but there is a subtle difference.\n", 12 | "\n", 13 | "* An **iterable** is a **representation** of a series of elements that can be iterated over. It does not have any iteration state such as a \"current element\". But every iterable can be converted to an iterator by using **iter()**. Typically, an iterable should be able to produce any number of valid iterators.\n", 14 | "\n", 15 | "* An **iterator** is the object with iteration state. It lets you check if it has more elements using the **next()** or **\\__next\\__()** and move to the next element (if any)." 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": 27, 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "class PowersOfTwo:\n", 25 | " def __init__(self, maximum=0):\n", 26 | " self.maximum = maximum\n", 27 | " def __iter__(self):\n", 28 | " self.n = 0\n", 29 | " return self\n", 30 | " def __next__(self):\n", 31 | " if self.n <= self.maximum:\n", 32 | " result = 2**self.n\n", 33 | " self.n += 1\n", 34 | " return result\n", 35 | " else:\n", 36 | " raise StopIteration" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 30, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "obj = iter(PowersOfTwo(5))" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 37, 51 | "metadata": {}, 52 | "outputs": [ 53 | { 54 | "ename": "StopIteration", 55 | "evalue": "", 56 | "output_type": "error", 57 | "traceback": [ 58 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 59 | "\u001b[0;31mStopIteration\u001b[0m Traceback (most recent call last)", 60 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 61 | "\u001b[0;32m\u001b[0m in \u001b[0;36m__next__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 13\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mStopIteration\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 62 | "\u001b[0;31mStopIteration\u001b[0m: " 63 | ] 64 | } 65 | ], 66 | "source": [ 67 | "next(obj)" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [] 76 | } 77 | ], 78 | "metadata": { 79 | "kernelspec": { 80 | "display_name": "Python 3", 81 | "language": "python", 82 | "name": "python3" 83 | }, 84 | "language_info": { 85 | "codemirror_mode": { 86 | "name": "ipython", 87 | "version": 3 88 | }, 89 | "file_extension": ".py", 90 | "mimetype": "text/x-python", 91 | "name": "python", 92 | "nbconvert_exporter": "python", 93 | "pygments_lexer": "ipython3", 94 | "version": "3.6.9" 95 | } 96 | }, 97 | "nbformat": 4, 98 | "nbformat_minor": 4 99 | } 100 | -------------------------------------------------------------------------------- /notebooks/09_generators.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #9\n", 8 | "\n", 9 | "## Generators\n", 10 | "\n", 11 | "* They are a simple way of creating iterators. All the work we have done is handled by generators.\n", 12 | "* They are easy to implement: we just have to create a function that returns elements with `yield` instead of `return`.\n", 13 | "* They can contain one or more `yield` statements.\n", 14 | "* When called, it returns an object (iterator) but does not start execution immediately.\n", 15 | "* Once the function yields, the function is paused and the control is transferred to the caller.\n", 16 | "* Local variables and their states are remembered between successive calls." 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "class PowersOfTwo:\n", 26 | " def __init__(self):\n", 27 | " pass\n", 28 | " def __iter__(self):\n", 29 | " self.n = 0\n", 30 | " return self\n", 31 | " def __next__(self):\n", 32 | " result = 2**self.n\n", 33 | " self.n += 1\n", 34 | " return result" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 2, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "obj = iter(PowersOfTwo())" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 10, 49 | "metadata": {}, 50 | "outputs": [ 51 | { 52 | "data": { 53 | "text/plain": [ 54 | "128" 55 | ] 56 | }, 57 | "execution_count": 10, 58 | "metadata": {}, 59 | "output_type": "execute_result" 60 | } 61 | ], 62 | "source": [ 63 | "next(obj)" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 20, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "def powers_of_two():\n", 73 | " i = 0\n", 74 | " while True:\n", 75 | " yield 2**i\n", 76 | " i += 1" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 21, 82 | "metadata": {}, 83 | "outputs": [], 84 | "source": [ 85 | "powers = powers_of_two()" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 29, 91 | "metadata": {}, 92 | "outputs": [ 93 | { 94 | "data": { 95 | "text/plain": [ 96 | "128" 97 | ] 98 | }, 99 | "execution_count": 29, 100 | "metadata": {}, 101 | "output_type": "execute_result" 102 | } 103 | ], 104 | "source": [ 105 | "next(powers)" 106 | ] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": {}, 111 | "source": [ 112 | "## Generator expressions" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": 30, 118 | "metadata": {}, 119 | "outputs": [], 120 | "source": [ 121 | "numbers = [3,6,8]\n", 122 | "powers = (x**2 for x in numbers)" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 34, 128 | "metadata": {}, 129 | "outputs": [ 130 | { 131 | "ename": "StopIteration", 132 | "evalue": "", 133 | "output_type": "error", 134 | "traceback": [ 135 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 136 | "\u001b[0;31mStopIteration\u001b[0m Traceback (most recent call last)", 137 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpowers\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 138 | "\u001b[0;31mStopIteration\u001b[0m: " 139 | ] 140 | } 141 | ], 142 | "source": [ 143 | "next(powers)" 144 | ] 145 | }, 146 | { 147 | "cell_type": "markdown", 148 | "metadata": {}, 149 | "source": [ 150 | "## Why use them?\n", 151 | "\n", 152 | "* Easier to implement than iterators\n", 153 | "* Memory efficient\n", 154 | "* Excellent to generate infinite streams\n", 155 | "* They can be pipelined" 156 | ] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "execution_count": 36, 161 | "metadata": {}, 162 | "outputs": [], 163 | "source": [ 164 | "numbers = [3,6,8]\n", 165 | "powers = (x**2 for x in numbers)" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": 37, 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [ 174 | "additions = (x+2 for x in powers)" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": 40, 180 | "metadata": {}, 181 | "outputs": [ 182 | { 183 | "data": { 184 | "text/plain": [ 185 | "66" 186 | ] 187 | }, 188 | "execution_count": 40, 189 | "metadata": {}, 190 | "output_type": "execute_result" 191 | } 192 | ], 193 | "source": [ 194 | "next(additions)" 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": null, 200 | "metadata": {}, 201 | "outputs": [], 202 | "source": [] 203 | } 204 | ], 205 | "metadata": { 206 | "kernelspec": { 207 | "display_name": "Python 3", 208 | "language": "python", 209 | "name": "python3" 210 | }, 211 | "language_info": { 212 | "codemirror_mode": { 213 | "name": "ipython", 214 | "version": 3 215 | }, 216 | "file_extension": ".py", 217 | "mimetype": "text/x-python", 218 | "name": "python", 219 | "nbconvert_exporter": "python", 220 | "pygments_lexer": "ipython3", 221 | "version": "3.6.9" 222 | } 223 | }, 224 | "nbformat": 4, 225 | "nbformat_minor": 4 226 | } 227 | -------------------------------------------------------------------------------- /notebooks/10_any_all.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #10\n", 8 | "## Any\n", 9 | "* Returns True if any element of an iterable is True and False otherwise.\n", 10 | "* At least one value is True $\\rightarrow$ True\n", 11 | "* All values are False $\\rightarrow$ False\n", 12 | "* Empty iterable $\\rightarrow$ False" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 5, 18 | "metadata": {}, 19 | "outputs": [ 20 | { 21 | "data": { 22 | "text/plain": [ 23 | "False" 24 | ] 25 | }, 26 | "execution_count": 5, 27 | "metadata": {}, 28 | "output_type": "execute_result" 29 | } 30 | ], 31 | "source": [ 32 | "fruits = [\"apple\", \"pineapple\", \"watermelon\", \"avocado\"]\n", 33 | "fruits_mapped = map(lambda fruit: len(fruit) > 50, fruits)\n", 34 | "any([])" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "## All\n", 42 | "* Return True if all elements of an iterable is True and False otherwise.\n", 43 | "* At least one value is False $\\rightarrow$ False\n", 44 | "* All values are True $\\rightarrow$ True\n", 45 | "* Empty iterable $\\rightarrow$ True" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 8, 51 | "metadata": {}, 52 | "outputs": [ 53 | { 54 | "data": { 55 | "text/plain": [ 56 | "True" 57 | ] 58 | }, 59 | "execution_count": 8, 60 | "metadata": {}, 61 | "output_type": "execute_result" 62 | } 63 | ], 64 | "source": [ 65 | "fruits_mapped = map(lambda fruit: len(fruit) < 50, fruits)\n", 66 | "all([])" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": null, 72 | "metadata": {}, 73 | "outputs": [], 74 | "source": [] 75 | } 76 | ], 77 | "metadata": { 78 | "kernelspec": { 79 | "display_name": "Python 3", 80 | "language": "python", 81 | "name": "python3" 82 | }, 83 | "language_info": { 84 | "codemirror_mode": { 85 | "name": "ipython", 86 | "version": 3 87 | }, 88 | "file_extension": ".py", 89 | "mimetype": "text/x-python", 90 | "name": "python", 91 | "nbconvert_exporter": "python", 92 | "pygments_lexer": "ipython3", 93 | "version": "3.6.9" 94 | } 95 | }, 96 | "nbformat": 4, 97 | "nbformat_minor": 4 98 | } 99 | -------------------------------------------------------------------------------- /notebooks/11_closures.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #11\n", 8 | "## Python closures\n", 9 | "\n", 10 | "* There are 3 things that we need in order to have a closure:\n", 11 | " 1. We must have a nested function\n", 12 | " 2. The nested function must refer to a value defined in the enclosing function\n", 13 | " 3. The enclosing function must return the nested function\n", 14 | "* Closures are useful for the next videos. So pay attention! " 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 7, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "def print_message(message):\n", 24 | " def printer():\n", 25 | " print(message)\n", 26 | " return printer" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 9, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "another_function = print_message(\"Hello\")" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 10, 41 | "metadata": {}, 42 | "outputs": [ 43 | { 44 | "name": "stdout", 45 | "output_type": "stream", 46 | "text": [ 47 | "Hello\n" 48 | ] 49 | } 50 | ], 51 | "source": [ 52 | "another_function()" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 11, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "del print_message" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 13, 67 | "metadata": {}, 68 | "outputs": [ 69 | { 70 | "name": "stdout", 71 | "output_type": "stream", 72 | "text": [ 73 | "Hello\n" 74 | ] 75 | } 76 | ], 77 | "source": [ 78 | "another_function()" 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": {}, 84 | "source": [ 85 | "## When to use closures?\n", 86 | "* Closures can avoid the use of global values and provides some form of data hiding. It can also provide an object oriented solution to the problem.\n", 87 | "* Decorators!" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": 14, 93 | "metadata": {}, 94 | "outputs": [], 95 | "source": [ 96 | "class Multiplier:\n", 97 | " def __init__(self, n):\n", 98 | " self.n = n\n", 99 | " def multiply(self, x):\n", 100 | " return x*self.n" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": 15, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "obj = Multiplier(5)" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 16, 115 | "metadata": {}, 116 | "outputs": [ 117 | { 118 | "data": { 119 | "text/plain": [ 120 | "35" 121 | ] 122 | }, 123 | "execution_count": 16, 124 | "metadata": {}, 125 | "output_type": "execute_result" 126 | } 127 | ], 128 | "source": [ 129 | "obj.multiply(7)" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 17, 135 | "metadata": {}, 136 | "outputs": [], 137 | "source": [ 138 | "def multiplier(n):\n", 139 | " def multiply(x):\n", 140 | " return x*n\n", 141 | " return multiply" 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "execution_count": 18, 147 | "metadata": {}, 148 | "outputs": [], 149 | "source": [ 150 | "multiplier_by_5 = multiplier(5)" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 19, 156 | "metadata": {}, 157 | "outputs": [ 158 | { 159 | "data": { 160 | "text/plain": [ 161 | "35" 162 | ] 163 | }, 164 | "execution_count": 19, 165 | "metadata": {}, 166 | "output_type": "execute_result" 167 | } 168 | ], 169 | "source": [ 170 | "multiplier_by_5(7)" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": null, 176 | "metadata": {}, 177 | "outputs": [], 178 | "source": [] 179 | } 180 | ], 181 | "metadata": { 182 | "kernelspec": { 183 | "display_name": "Python 3", 184 | "language": "python", 185 | "name": "python3" 186 | }, 187 | "language_info": { 188 | "codemirror_mode": { 189 | "name": "ipython", 190 | "version": 3 191 | }, 192 | "file_extension": ".py", 193 | "mimetype": "text/x-python", 194 | "name": "python", 195 | "nbconvert_exporter": "python", 196 | "pygments_lexer": "ipython3", 197 | "version": "3.6.9" 198 | } 199 | }, 200 | "nbformat": 4, 201 | "nbformat_minor": 4 202 | } 203 | -------------------------------------------------------------------------------- /notebooks/12_args_kwargs.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #12\n", 8 | "## \\*args and \\**kwargs\n", 9 | "\n", 10 | "* In Python, we can pass a variable number of arguments to a function using some special symbols:\n", 11 | " 1. *args (non-keyword arguments)\n", 12 | " 2. **kwargs (keyword arguments)" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "## \\*args\n", 20 | "\n", 21 | "It allows us to pass a variable number of parameters, which will be encapsulated in a tuple." 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 38, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "def add(*args):\n", 31 | " print(args)\n", 32 | " return sum(args)" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 39, 38 | "metadata": {}, 39 | "outputs": [ 40 | { 41 | "name": "stdout", 42 | "output_type": "stream", 43 | "text": [ 44 | "(1, 4, 6, 8, 3)\n" 45 | ] 46 | }, 47 | { 48 | "data": { 49 | "text/plain": [ 50 | "22" 51 | ] 52 | }, 53 | "execution_count": 39, 54 | "metadata": {}, 55 | "output_type": "execute_result" 56 | } 57 | ], 58 | "source": [ 59 | "add(1,4,6,8,3)" 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "## \\**kwargs\n", 67 | "\n", 68 | "Python can pass a variable number of keyword arguments using **\\*\\*kwargs**." 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": 36, 74 | "metadata": {}, 75 | "outputs": [], 76 | "source": [ 77 | "def print_fruits(**kwargs):\n", 78 | " print(kwargs)\n", 79 | " for key, value in kwargs.items():\n", 80 | " print(key, value)" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": 37, 86 | "metadata": {}, 87 | "outputs": [ 88 | { 89 | "name": "stdout", 90 | "output_type": "stream", 91 | "text": [ 92 | "{'apple': 60, 'watermelon': 100, 'grapes': 200}\n", 93 | "apple 60\n", 94 | "watermelon 100\n", 95 | "grapes 200\n" 96 | ] 97 | } 98 | ], 99 | "source": [ 100 | "print_fruits(apple=60, watermelon=100, grapes=200)" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": null, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [] 109 | } 110 | ], 111 | "metadata": { 112 | "kernelspec": { 113 | "display_name": "Python 3", 114 | "language": "python", 115 | "name": "python3" 116 | }, 117 | "language_info": { 118 | "codemirror_mode": { 119 | "name": "ipython", 120 | "version": 3 121 | }, 122 | "file_extension": ".py", 123 | "mimetype": "text/x-python", 124 | "name": "python", 125 | "nbconvert_exporter": "python", 126 | "pygments_lexer": "ipython3", 127 | "version": "3.6.9" 128 | } 129 | }, 130 | "nbformat": 4, 131 | "nbformat_minor": 4 132 | } 133 | -------------------------------------------------------------------------------- /notebooks/13_decorators.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #13\n", 8 | "## Decorators\n", 9 | "\n", 10 | "* In Python (and other programming languages), you can pass functions as arguments to other functions.\n", 11 | "* We have already done this with functions like `filter` and `map`.\n", 12 | "* Such functions are called **higher order functions** and you may have found abbreviations like **HOF**.\n", 13 | "* HOF can return functions, as we saw in closures.\n", 14 | "* **Decorators** in simple terms, takes a function, adds some extra functionalities, and returns it." 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 1, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "def wrapper(f):\n", 24 | " def inner():\n", 25 | " print(\"I am a decorated function\")\n", 26 | " f()\n", 27 | " return inner" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 6, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "@wrapper\n", 37 | "def hello_world():\n", 38 | " print(\"Hello world!\")" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 7, 44 | "metadata": {}, 45 | "outputs": [ 46 | { 47 | "name": "stdout", 48 | "output_type": "stream", 49 | "text": [ 50 | "I am a decorated function\n", 51 | "Hello world!\n" 52 | ] 53 | } 54 | ], 55 | "source": [ 56 | "hello_world()" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 12, 62 | "metadata": {}, 63 | "outputs": [], 64 | "source": [ 65 | "def wrapper(f):\n", 66 | " def inner(a, b):\n", 67 | " if b == 0:\n", 68 | " print(\"We cannot use b as zero\")\n", 69 | " return\n", 70 | " else:\n", 71 | " return f(a, b)\n", 72 | " return inner" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 13, 78 | "metadata": {}, 79 | "outputs": [], 80 | "source": [ 81 | "@wrapper\n", 82 | "def divide(a, b):\n", 83 | " return a/b" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 15, 89 | "metadata": {}, 90 | "outputs": [ 91 | { 92 | "name": "stdout", 93 | "output_type": "stream", 94 | "text": [ 95 | "We cannot use b as zero\n" 96 | ] 97 | } 98 | ], 99 | "source": [ 100 | "divide(1,0)" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": 19, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "import time\n", 110 | "\n", 111 | "def wrapper(f):\n", 112 | " def inner(*args, **kwargs):\n", 113 | " start = time.time()\n", 114 | " f(*args, **kwargs)\n", 115 | " end = time.time()\n", 116 | " execution_time = end-start\n", 117 | " print(f\"This function took {execution_time} seconds\")\n", 118 | " return inner" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 20, 124 | "metadata": {}, 125 | "outputs": [], 126 | "source": [ 127 | "@wrapper\n", 128 | "def complicated_operation(a, b, c):\n", 129 | " r = a+b+c\n", 130 | " r *= a\n", 131 | " r /= c\n", 132 | " print(r)" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": 21, 138 | "metadata": {}, 139 | "outputs": [ 140 | { 141 | "name": "stdout", 142 | "output_type": "stream", 143 | "text": [ 144 | "8.421052631578947\n", 145 | "This function took 7.677078247070312e-05 seconds\n" 146 | ] 147 | } 148 | ], 149 | "source": [ 150 | "complicated_operation(5, 8, 19)" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": null, 156 | "metadata": {}, 157 | "outputs": [], 158 | "source": [] 159 | } 160 | ], 161 | "metadata": { 162 | "kernelspec": { 163 | "display_name": "Python 3", 164 | "language": "python", 165 | "name": "python3" 166 | }, 167 | "language_info": { 168 | "codemirror_mode": { 169 | "name": "ipython", 170 | "version": 3 171 | }, 172 | "file_extension": ".py", 173 | "mimetype": "text/x-python", 174 | "name": "python", 175 | "nbconvert_exporter": "python", 176 | "pygments_lexer": "ipython3", 177 | "version": "3.6.9" 178 | } 179 | }, 180 | "nbformat": 4, 181 | "nbformat_minor": 4 182 | } 183 | -------------------------------------------------------------------------------- /notebooks/14_chaining_decorators.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #14\n", 8 | "## Chaining decorators\n", 9 | "\n", 10 | "* Before we move on, I wanted to tell you that you will find decorators everywhere from now on:\n", 11 | "![flask](https://upload.wikimedia.org/wikipedia/commons/thumb/3/3c/Flask_logo.svg/1200px-Flask_logo.svg.png)\n", 12 | "* For example, in Flask, you will find decorators in the first program you write is going to be this:" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 1, 18 | "metadata": {}, 19 | "outputs": [], 20 | "source": [ 21 | "from flask import Flask\n", 22 | "app = Flask(__name__)\n", 23 | "\n", 24 | "@app.route('/')\n", 25 | "def hello_world():\n", 26 | " return 'Hello, World!'" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 2, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "def wrapper_1(f):\n", 36 | " def inner(*args, **kwargs):\n", 37 | " print(\"I am the first decorator\")\n", 38 | " f(*args, **kwargs)\n", 39 | " print(\"I am the end of the first decorator\")\n", 40 | " return inner" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": 3, 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "def wrapper_2(f):\n", 50 | " def inner(*args, **kwargs):\n", 51 | " print(\"I am the second decorator\")\n", 52 | " f(*args, **kwargs)\n", 53 | " print(\"I am the end of the second decorator\")\n", 54 | " return inner" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 8, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "@wrapper_1\n", 64 | "@wrapper_2\n", 65 | "def hello_world():\n", 66 | " print(\"Hello world!\")" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 9, 72 | "metadata": {}, 73 | "outputs": [ 74 | { 75 | "name": "stdout", 76 | "output_type": "stream", 77 | "text": [ 78 | "I am the first decorator\n", 79 | "I am the second decorator\n", 80 | "Hello world!\n", 81 | "I am the end of the second decorator\n", 82 | "I am the end of the first decorator\n" 83 | ] 84 | } 85 | ], 86 | "source": [ 87 | "hello_world()" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": null, 93 | "metadata": {}, 94 | "outputs": [], 95 | "source": [] 96 | } 97 | ], 98 | "metadata": { 99 | "kernelspec": { 100 | "display_name": "Python 3", 101 | "language": "python", 102 | "name": "python3" 103 | }, 104 | "language_info": { 105 | "codemirror_mode": { 106 | "name": "ipython", 107 | "version": 3 108 | }, 109 | "file_extension": ".py", 110 | "mimetype": "text/x-python", 111 | "name": "python", 112 | "nbconvert_exporter": "python", 113 | "pygments_lexer": "ipython3", 114 | "version": "3.6.9" 115 | } 116 | }, 117 | "nbformat": 4, 118 | "nbformat_minor": 4 119 | } 120 | -------------------------------------------------------------------------------- /notebooks/15_property.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #15\n", 8 | "## The @property decorator\n", 9 | "* It helps us to define setters and getters for classes in a convenient way." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 32, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "class Person:\n", 19 | " def __init__(self, age):\n", 20 | " self.age = age\n", 21 | " \n", 22 | " @property\n", 23 | " def age(self):\n", 24 | " print(\"Getting the age...\")\n", 25 | " return self._age\n", 26 | " \n", 27 | " @age.setter\n", 28 | " def age(self, age):\n", 29 | " if age < 0:\n", 30 | " print(\"We cannot have negative ages\")\n", 31 | " else:\n", 32 | " print(\"Setting the age...\")\n", 33 | " self._age = age\n", 34 | " \n", 35 | " def category(self):\n", 36 | " if self.age < 13:\n", 37 | " return \"Kid\"\n", 38 | " elif self.age >= 13 and self.age < 18:\n", 39 | " return \"Teen\"\n", 40 | " elif self.age >= 18 and self.age < 65:\n", 41 | " return \"Adult\"\n", 42 | " else:\n", 43 | " return \"Elderly\"" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 33, 49 | "metadata": {}, 50 | "outputs": [ 51 | { 52 | "name": "stdout", 53 | "output_type": "stream", 54 | "text": [ 55 | "Setting the age...\n" 56 | ] 57 | } 58 | ], 59 | "source": [ 60 | "person = Person(25)" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": 34, 66 | "metadata": {}, 67 | "outputs": [ 68 | { 69 | "name": "stdout", 70 | "output_type": "stream", 71 | "text": [ 72 | "Setting the age...\n" 73 | ] 74 | } 75 | ], 76 | "source": [ 77 | "person.age = 13" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 35, 83 | "metadata": {}, 84 | "outputs": [ 85 | { 86 | "name": "stdout", 87 | "output_type": "stream", 88 | "text": [ 89 | "We cannot have negative ages\n" 90 | ] 91 | } 92 | ], 93 | "source": [ 94 | "person.age = -4" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": 36, 100 | "metadata": {}, 101 | "outputs": [ 102 | { 103 | "name": "stdout", 104 | "output_type": "stream", 105 | "text": [ 106 | "Getting the age...\n" 107 | ] 108 | }, 109 | { 110 | "data": { 111 | "text/plain": [ 112 | "13" 113 | ] 114 | }, 115 | "execution_count": 36, 116 | "metadata": {}, 117 | "output_type": "execute_result" 118 | } 119 | ], 120 | "source": [ 121 | "person.age" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": 37, 127 | "metadata": {}, 128 | "outputs": [ 129 | { 130 | "name": "stdout", 131 | "output_type": "stream", 132 | "text": [ 133 | "Getting the age...\n", 134 | "Getting the age...\n", 135 | "Getting the age...\n" 136 | ] 137 | }, 138 | { 139 | "data": { 140 | "text/plain": [ 141 | "'Teen'" 142 | ] 143 | }, 144 | "execution_count": 37, 145 | "metadata": {}, 146 | "output_type": "execute_result" 147 | } 148 | ], 149 | "source": [ 150 | "person.category()" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": null, 156 | "metadata": {}, 157 | "outputs": [], 158 | "source": [] 159 | } 160 | ], 161 | "metadata": { 162 | "kernelspec": { 163 | "display_name": "Python 3", 164 | "language": "python", 165 | "name": "python3" 166 | }, 167 | "language_info": { 168 | "codemirror_mode": { 169 | "name": "ipython", 170 | "version": 3 171 | }, 172 | "file_extension": ".py", 173 | "mimetype": "text/x-python", 174 | "name": "python", 175 | "nbconvert_exporter": "python", 176 | "pygments_lexer": "ipython3", 177 | "version": "3.6.9" 178 | } 179 | }, 180 | "nbformat": 4, 181 | "nbformat_minor": 4 182 | } 183 | -------------------------------------------------------------------------------- /notebooks/16_classmethod.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #16\n", 8 | "## The @classmethod decorator\n", 9 | "### What is a class method? \n", 10 | "* A class method is a method that is bound to a class rather than its object. \n", 11 | "* It doesn't require creation of a class instance.\n", 12 | "* Class method works with the class since its parameter is always the class itself.\n", 13 | "* The first argument has to be the class where it's attached: `def class_method(cls, args...)`.\n", 14 | "\n", 15 | "### When are they used?\n", 16 | "* Generally, they are useful to create factory methods.\n", 17 | "\n", 18 | "#### But what are factory methods?\n", 19 | "* Factory methods are those methods which return a class object." 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 4, 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "from datetime import date\n", 29 | "\n", 30 | "class Person:\n", 31 | " def __init__(self, age):\n", 32 | " self.age = age\n", 33 | " def display_age(self):\n", 34 | " print(f\"The age of the person is {self.age}\")\n", 35 | " @classmethod\n", 36 | " def person_from_birthyear(cls, birthyear):\n", 37 | " calculated_age = date.today().year - birthyear\n", 38 | " return cls(calculated_age)" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 5, 44 | "metadata": {}, 45 | "outputs": [], 46 | "source": [ 47 | "person = Person(25)" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 6, 53 | "metadata": {}, 54 | "outputs": [ 55 | { 56 | "name": "stdout", 57 | "output_type": "stream", 58 | "text": [ 59 | "The age of the person is 25\n" 60 | ] 61 | } 62 | ], 63 | "source": [ 64 | "person.display_age()" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 7, 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "person_1 = Person.person_from_birthyear(1998)" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 8, 79 | "metadata": {}, 80 | "outputs": [ 81 | { 82 | "data": { 83 | "text/plain": [ 84 | "22" 85 | ] 86 | }, 87 | "execution_count": 8, 88 | "metadata": {}, 89 | "output_type": "execute_result" 90 | } 91 | ], 92 | "source": [ 93 | "person_1.age" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": 9, 99 | "metadata": {}, 100 | "outputs": [ 101 | { 102 | "name": "stdout", 103 | "output_type": "stream", 104 | "text": [ 105 | "The age of the person is 22\n" 106 | ] 107 | } 108 | ], 109 | "source": [ 110 | "person_1.display_age()" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": 10, 116 | "metadata": {}, 117 | "outputs": [], 118 | "source": [ 119 | "class Employee(Person):\n", 120 | " pass" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": 11, 126 | "metadata": {}, 127 | "outputs": [], 128 | "source": [ 129 | "employee = Employee.person_from_birthyear(1990)" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 13, 135 | "metadata": {}, 136 | "outputs": [ 137 | { 138 | "name": "stdout", 139 | "output_type": "stream", 140 | "text": [ 141 | "The age of the person is 30\n" 142 | ] 143 | } 144 | ], 145 | "source": [ 146 | "employee.display_age()" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": 14, 152 | "metadata": {}, 153 | "outputs": [ 154 | { 155 | "data": { 156 | "text/plain": [ 157 | "True" 158 | ] 159 | }, 160 | "execution_count": 14, 161 | "metadata": {}, 162 | "output_type": "execute_result" 163 | } 164 | ], 165 | "source": [ 166 | "isinstance(employee, Employee)" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": 15, 172 | "metadata": {}, 173 | "outputs": [ 174 | { 175 | "data": { 176 | "text/plain": [ 177 | "__main__.Employee" 178 | ] 179 | }, 180 | "execution_count": 15, 181 | "metadata": {}, 182 | "output_type": "execute_result" 183 | } 184 | ], 185 | "source": [ 186 | "type(employee)" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [] 195 | } 196 | ], 197 | "metadata": { 198 | "kernelspec": { 199 | "display_name": "Python 3", 200 | "language": "python", 201 | "name": "python3" 202 | }, 203 | "language_info": { 204 | "codemirror_mode": { 205 | "name": "ipython", 206 | "version": 3 207 | }, 208 | "file_extension": ".py", 209 | "mimetype": "text/x-python", 210 | "name": "python", 211 | "nbconvert_exporter": "python", 212 | "pygments_lexer": "ipython3", 213 | "version": "3.6.9" 214 | } 215 | }, 216 | "nbformat": 4, 217 | "nbformat_minor": 4 218 | } 219 | -------------------------------------------------------------------------------- /notebooks/17_staticmethod.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #17\n", 8 | "## The @staticmethod decorator\n", 9 | "### What is a static method? \n", 10 | "* Static methods, much like class methods, are methods that are bound to a class rather than its object.\n", 11 | "* They do not require a class instance creation. So, they are not dependent on the state of the object.\n", 12 | "* The difference between a static method and a class method is:\n", 13 | " * Static method knows nothing about the class and just deals with the parameters.\n", 14 | " * Class method works with the class since its parameter is always the class itself.\n", 15 | " \n", 16 | "### When are they used?\n", 17 | "* Generally, they are useful to group utility functions to a class." 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 11, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "import time\n", 27 | "\n", 28 | "class Hour:\n", 29 | " def __init__(self, seconds):\n", 30 | " self.seconds = seconds\n", 31 | " @staticmethod\n", 32 | " def convert_seconds_to_hour(seconds):\n", 33 | " return time.strftime(\"%H:%M:%S\", time.gmtime(seconds))\n", 34 | " def display_hour(self):\n", 35 | " hour = self.convert_seconds_to_hour(self.seconds)\n", 36 | " print(f\"The hour is: {hour}\")" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 12, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "hour_1 = Hour(65)" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 13, 51 | "metadata": {}, 52 | "outputs": [ 53 | { 54 | "name": "stdout", 55 | "output_type": "stream", 56 | "text": [ 57 | "The hour is: 00:01:05\n" 58 | ] 59 | } 60 | ], 61 | "source": [ 62 | "hour_1.display_hour()" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 14, 68 | "metadata": {}, 69 | "outputs": [ 70 | { 71 | "data": { 72 | "text/plain": [ 73 | "'00:01:05'" 74 | ] 75 | }, 76 | "execution_count": 14, 77 | "metadata": {}, 78 | "output_type": "execute_result" 79 | } 80 | ], 81 | "source": [ 82 | "Hour.convert_seconds_to_hour(65)" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": null, 88 | "metadata": {}, 89 | "outputs": [], 90 | "source": [] 91 | } 92 | ], 93 | "metadata": { 94 | "kernelspec": { 95 | "display_name": "Python 3", 96 | "language": "python", 97 | "name": "python3" 98 | }, 99 | "language_info": { 100 | "codemirror_mode": { 101 | "name": "ipython", 102 | "version": 3 103 | }, 104 | "file_extension": ".py", 105 | "mimetype": "text/x-python", 106 | "name": "python", 107 | "nbconvert_exporter": "python", 108 | "pygments_lexer": "ipython3", 109 | "version": "3.6.9" 110 | } 111 | }, 112 | "nbformat": 4, 113 | "nbformat_minor": 4 114 | } 115 | -------------------------------------------------------------------------------- /notebooks/18_reduce.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #18\n", 8 | "## The reduce function\n", 9 | "* Applies function of two arguments cumulatively to the items of iterable, from left to right, so as to reduce the iterable to a single value.\n", 10 | "* It's the contrary to the `map` function.\n", 11 | "* Extremely used in Big Data\n", 12 | "![mapreduce](https://miro.medium.com/max/1838/1*1gx5I6RbBoJieKjT-mzRzA.png)" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 10, 18 | "metadata": {}, 19 | "outputs": [], 20 | "source": [ 21 | "from functools import reduce" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 16, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "from operator import mul" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 18, 36 | "metadata": {}, 37 | "outputs": [ 38 | { 39 | "data": { 40 | "text/plain": [ 41 | "1200" 42 | ] 43 | }, 44 | "execution_count": 18, 45 | "metadata": {}, 46 | "output_type": "execute_result" 47 | } 48 | ], 49 | "source": [ 50 | "reduce(mul, [1, 2, 3, 4, 5], 10)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "## What's actually happening here?\n", 58 | "\n", 59 | "In the lambda function, `x` is the accumulated value while `y` is the current value. So, in the first \"iteration\", we are doing:\n", 60 | "* (1+2)\n", 61 | "Then, we are doing:\n", 62 | "* ((1+2)+3)\n", 63 | "Then:\n", 64 | "* (((1+2)+3)+4)\n", 65 | "Then:\n", 66 | "* ((((1+2)+3)+4)+5)" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 19, 72 | "metadata": {}, 73 | "outputs": [], 74 | "source": [ 75 | "def factorial(n):\n", 76 | " return reduce(mul, range(1, n+1))" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 20, 82 | "metadata": {}, 83 | "outputs": [ 84 | { 85 | "data": { 86 | "text/plain": [ 87 | "120" 88 | ] 89 | }, 90 | "execution_count": 20, 91 | "metadata": {}, 92 | "output_type": "execute_result" 93 | } 94 | ], 95 | "source": [ 96 | "factorial(5)" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": null, 102 | "metadata": {}, 103 | "outputs": [], 104 | "source": [] 105 | } 106 | ], 107 | "metadata": { 108 | "kernelspec": { 109 | "display_name": "Python 3", 110 | "language": "python", 111 | "name": "python3" 112 | }, 113 | "language_info": { 114 | "codemirror_mode": { 115 | "name": "ipython", 116 | "version": 3 117 | }, 118 | "file_extension": ".py", 119 | "mimetype": "text/x-python", 120 | "name": "python", 121 | "nbconvert_exporter": "python", 122 | "pygments_lexer": "ipython3", 123 | "version": "3.6.9" 124 | } 125 | }, 126 | "nbformat": 4, 127 | "nbformat_minor": 4 128 | } 129 | -------------------------------------------------------------------------------- /notebooks/19_accumulate.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #19\n", 8 | "## The accumulate function\n", 9 | "* It's similar to the `reduce` function, but it returns the intermediate results!\n", 10 | "* You have to import it from the `itertools` library and not from `functools`. \n", 11 | "* The first argument is not the function, it is the iterable." 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 6, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "from itertools import accumulate" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 7, 26 | "metadata": {}, 27 | "outputs": [], 28 | "source": [ 29 | "from operator import mul" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 8, 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "numbers = [1,4,7,3,2]\n", 39 | "result = accumulate(numbers, mul)" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 9, 45 | "metadata": {}, 46 | "outputs": [ 47 | { 48 | "name": "stdout", 49 | "output_type": "stream", 50 | "text": [ 51 | "\n" 52 | ] 53 | } 54 | ], 55 | "source": [ 56 | "print(result)" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 10, 62 | "metadata": {}, 63 | "outputs": [ 64 | { 65 | "name": "stdout", 66 | "output_type": "stream", 67 | "text": [ 68 | "1\n", 69 | "4\n", 70 | "28\n", 71 | "84\n", 72 | "168\n" 73 | ] 74 | } 75 | ], 76 | "source": [ 77 | "for step in result:\n", 78 | " print(step)" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [] 87 | } 88 | ], 89 | "metadata": { 90 | "kernelspec": { 91 | "display_name": "Python 3", 92 | "language": "python", 93 | "name": "python3" 94 | }, 95 | "language_info": { 96 | "codemirror_mode": { 97 | "name": "ipython", 98 | "version": 3 99 | }, 100 | "file_extension": ".py", 101 | "mimetype": "text/x-python", 102 | "name": "python", 103 | "nbconvert_exporter": "python", 104 | "pygments_lexer": "ipython3", 105 | "version": "3.6.9" 106 | } 107 | }, 108 | "nbformat": 4, 109 | "nbformat_minor": 4 110 | } 111 | -------------------------------------------------------------------------------- /notebooks/20_get_dictionary.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #20\n", 8 | "## Getting and setting values properly in a dictionary" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "metadata": {}, 15 | "outputs": [], 16 | "source": [ 17 | "fruits = {\"apple\": 60, \"watermelon\": 70, \"grapes\": 200}" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 6, 23 | "metadata": {}, 24 | "outputs": [ 25 | { 26 | "name": "stdout", 27 | "output_type": "stream", 28 | "text": [ 29 | "None\n" 30 | ] 31 | } 32 | ], 33 | "source": [ 34 | "fruits.get(\"apples\")" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 7, 40 | "metadata": {}, 41 | "outputs": [ 42 | { 43 | "data": { 44 | "text/plain": [ 45 | "{'apple': 60, 'watermelon': 70, 'grapes': 200}" 46 | ] 47 | }, 48 | "execution_count": 7, 49 | "metadata": {}, 50 | "output_type": "execute_result" 51 | } 52 | ], 53 | "source": [ 54 | "fruits" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 9, 60 | "metadata": {}, 61 | "outputs": [ 62 | { 63 | "data": { 64 | "text/plain": [ 65 | "0" 66 | ] 67 | }, 68 | "execution_count": 9, 69 | "metadata": {}, 70 | "output_type": "execute_result" 71 | } 72 | ], 73 | "source": [ 74 | "fruits.setdefault(\"apples\", 0)" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 10, 80 | "metadata": {}, 81 | "outputs": [ 82 | { 83 | "data": { 84 | "text/plain": [ 85 | "{'apple': 60, 'watermelon': 70, 'grapes': 200, 'apples': 0}" 86 | ] 87 | }, 88 | "execution_count": 10, 89 | "metadata": {}, 90 | "output_type": "execute_result" 91 | } 92 | ], 93 | "source": [ 94 | "fruits" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": 11, 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [ 103 | "fruits_list = [\"apple\", \"watermelon\", \"apple\"]" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 14, 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [ 112 | "quantities = dict()\n", 113 | "for fruit in fruits_list:\n", 114 | " quantities[fruit] = quantities.setdefault(fruit, 0) + 1" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": 15, 120 | "metadata": {}, 121 | "outputs": [ 122 | { 123 | "data": { 124 | "text/plain": [ 125 | "{'apple': 2, 'watermelon': 1}" 126 | ] 127 | }, 128 | "execution_count": 15, 129 | "metadata": {}, 130 | "output_type": "execute_result" 131 | } 132 | ], 133 | "source": [ 134 | "quantities" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": null, 140 | "metadata": {}, 141 | "outputs": [], 142 | "source": [] 143 | } 144 | ], 145 | "metadata": { 146 | "kernelspec": { 147 | "display_name": "Python 3", 148 | "language": "python", 149 | "name": "python3" 150 | }, 151 | "language_info": { 152 | "codemirror_mode": { 153 | "name": "ipython", 154 | "version": 3 155 | }, 156 | "file_extension": ".py", 157 | "mimetype": "text/x-python", 158 | "name": "python", 159 | "nbconvert_exporter": "python", 160 | "pygments_lexer": "ipython3", 161 | "version": "3.6.9" 162 | } 163 | }, 164 | "nbformat": 4, 165 | "nbformat_minor": 4 166 | } 167 | -------------------------------------------------------------------------------- /notebooks/21_counter.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #21\n", 8 | "\n", 9 | "## The Counter class\n", 10 | "\n", 11 | "* A Counter is a dict subclass for counting hashable objects. It is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values. \n", 12 | "* Counts are allowed to be any integer value including zero or negative counts. The Counter class is similar to bags or multisets in other languages.\n", 13 | "* Elements are counted from an iterable or initialized from another mapping (or counter)" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 1, 19 | "metadata": {}, 20 | "outputs": [], 21 | "source": [ 22 | "from collections import Counter" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 2, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "fruits = [\"apple\", \"apple\", \"apple\", \"watermelon\", \"grapes\", \"grapes\"]" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 3, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "counts = Counter(fruits)" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": 4, 46 | "metadata": {}, 47 | "outputs": [ 48 | { 49 | "data": { 50 | "text/plain": [ 51 | "Counter({'apple': 3, 'watermelon': 1, 'grapes': 2})" 52 | ] 53 | }, 54 | "execution_count": 4, 55 | "metadata": {}, 56 | "output_type": "execute_result" 57 | } 58 | ], 59 | "source": [ 60 | "counts" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": 9, 66 | "metadata": {}, 67 | "outputs": [ 68 | { 69 | "data": { 70 | "text/plain": [ 71 | "0" 72 | ] 73 | }, 74 | "execution_count": 9, 75 | "metadata": {}, 76 | "output_type": "execute_result" 77 | } 78 | ], 79 | "source": [ 80 | "counts.get(\"apples\", 0)" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": 10, 86 | "metadata": {}, 87 | "outputs": [ 88 | { 89 | "data": { 90 | "text/plain": [ 91 | "0" 92 | ] 93 | }, 94 | "execution_count": 10, 95 | "metadata": {}, 96 | "output_type": "execute_result" 97 | } 98 | ], 99 | "source": [ 100 | "counts[\"apples\"]" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": 14, 106 | "metadata": {}, 107 | "outputs": [ 108 | { 109 | "data": { 110 | "text/plain": [ 111 | "[('apple', 3)]" 112 | ] 113 | }, 114 | "execution_count": 14, 115 | "metadata": {}, 116 | "output_type": "execute_result" 117 | } 118 | ], 119 | "source": [ 120 | "counts.most_common(1)" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": 15, 126 | "metadata": {}, 127 | "outputs": [], 128 | "source": [ 129 | "counts = Counter(\"mississipi\")" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 16, 135 | "metadata": {}, 136 | "outputs": [ 137 | { 138 | "data": { 139 | "text/plain": [ 140 | "Counter({'m': 1, 'i': 4, 's': 4, 'p': 1})" 141 | ] 142 | }, 143 | "execution_count": 16, 144 | "metadata": {}, 145 | "output_type": "execute_result" 146 | } 147 | ], 148 | "source": [ 149 | "counts" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": null, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [] 158 | } 159 | ], 160 | "metadata": { 161 | "kernelspec": { 162 | "display_name": "Python 3", 163 | "language": "python", 164 | "name": "python3" 165 | }, 166 | "language_info": { 167 | "codemirror_mode": { 168 | "name": "ipython", 169 | "version": 3 170 | }, 171 | "file_extension": ".py", 172 | "mimetype": "text/x-python", 173 | "name": "python", 174 | "nbconvert_exporter": "python", 175 | "pygments_lexer": "ipython3", 176 | "version": "3.6.9" 177 | } 178 | }, 179 | "nbformat": 4, 180 | "nbformat_minor": 4 181 | } 182 | -------------------------------------------------------------------------------- /notebooks/22_sets.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #22\n", 8 | "\n", 9 | "## Sets\n", 10 | "\n", 11 | "* A set is a collection which is unordered and unindexed.\n", 12 | "* It is iterable, mutable and has no duplicate elements.\n", 13 | "* Python’s set class represents the mathematical notion of a set.\n", 14 | "* The major advantage of using a set, as opposed to a list, is that it has a highly optimized method for checking whether a specific element is contained in the set." 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 50, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "fruits = [\"apple\", \"apple\", \"apple\", \"watermelon\", \"grapes\", \"grapes\"]" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 51, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "fruits_set = set(fruits)" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 52, 38 | "metadata": {}, 39 | "outputs": [ 40 | { 41 | "data": { 42 | "text/plain": [ 43 | "{'apple', 'grapes', 'watermelon'}" 44 | ] 45 | }, 46 | "execution_count": 52, 47 | "metadata": {}, 48 | "output_type": "execute_result" 49 | } 50 | ], 51 | "source": [ 52 | "fruits_set" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 53, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "another_fruits_set = {\"lemon\", \"pineapple\", \"mango\", \"peach\", \"grapes\"}" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 54, 67 | "metadata": {}, 68 | "outputs": [ 69 | { 70 | "data": { 71 | "text/plain": [ 72 | "set" 73 | ] 74 | }, 75 | "execution_count": 54, 76 | "metadata": {}, 77 | "output_type": "execute_result" 78 | } 79 | ], 80 | "source": [ 81 | "type(another_fruits_set)" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 59, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "empty_set = set()" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": 60, 96 | "metadata": {}, 97 | "outputs": [ 98 | { 99 | "data": { 100 | "text/plain": [ 101 | "set" 102 | ] 103 | }, 104 | "execution_count": 60, 105 | "metadata": {}, 106 | "output_type": "execute_result" 107 | } 108 | ], 109 | "source": [ 110 | "type(empty_set)" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": 63, 116 | "metadata": {}, 117 | "outputs": [], 118 | "source": [ 119 | "fruits_set.add(\"banana\")" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 64, 125 | "metadata": {}, 126 | "outputs": [ 127 | { 128 | "data": { 129 | "text/plain": [ 130 | "{'apple', 'banana', 'grapes', 'watermelon'}" 131 | ] 132 | }, 133 | "execution_count": 64, 134 | "metadata": {}, 135 | "output_type": "execute_result" 136 | } 137 | ], 138 | "source": [ 139 | "fruits_set" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 65, 145 | "metadata": {}, 146 | "outputs": [], 147 | "source": [ 148 | "fruits_set.update([\"banana\", \"melon\", \"grapes\"])" 149 | ] 150 | }, 151 | { 152 | "cell_type": "code", 153 | "execution_count": 66, 154 | "metadata": {}, 155 | "outputs": [ 156 | { 157 | "data": { 158 | "text/plain": [ 159 | "{'apple', 'banana', 'grapes', 'melon', 'watermelon'}" 160 | ] 161 | }, 162 | "execution_count": 66, 163 | "metadata": {}, 164 | "output_type": "execute_result" 165 | } 166 | ], 167 | "source": [ 168 | "fruits_set" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": 68, 174 | "metadata": {}, 175 | "outputs": [], 176 | "source": [ 177 | "fruits_set.remove(\"banana\")" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": 69, 183 | "metadata": {}, 184 | "outputs": [ 185 | { 186 | "data": { 187 | "text/plain": [ 188 | "{'apple', 'grapes', 'melon', 'watermelon'}" 189 | ] 190 | }, 191 | "execution_count": 69, 192 | "metadata": {}, 193 | "output_type": "execute_result" 194 | } 195 | ], 196 | "source": [ 197 | "fruits_set" 198 | ] 199 | }, 200 | { 201 | "cell_type": "code", 202 | "execution_count": 70, 203 | "metadata": {}, 204 | "outputs": [ 205 | { 206 | "ename": "KeyError", 207 | "evalue": "'banana'", 208 | "output_type": "error", 209 | "traceback": [ 210 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 211 | "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", 212 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfruits_set\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mremove\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"banana\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 213 | "\u001b[0;31mKeyError\u001b[0m: 'banana'" 214 | ] 215 | } 216 | ], 217 | "source": [ 218 | "fruits_set.remove(\"banana\")" 219 | ] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "execution_count": 71, 224 | "metadata": {}, 225 | "outputs": [], 226 | "source": [ 227 | "fruits_set.discard(\"banana\")" 228 | ] 229 | }, 230 | { 231 | "cell_type": "code", 232 | "execution_count": 72, 233 | "metadata": {}, 234 | "outputs": [ 235 | { 236 | "data": { 237 | "text/plain": [ 238 | "['apple', 'apple', 'apple', 'watermelon', 'grapes', 'grapes']" 239 | ] 240 | }, 241 | "execution_count": 72, 242 | "metadata": {}, 243 | "output_type": "execute_result" 244 | } 245 | ], 246 | "source": [ 247 | "fruits" 248 | ] 249 | }, 250 | { 251 | "cell_type": "code", 252 | "execution_count": 73, 253 | "metadata": {}, 254 | "outputs": [ 255 | { 256 | "data": { 257 | "text/plain": [ 258 | "'grapes'" 259 | ] 260 | }, 261 | "execution_count": 73, 262 | "metadata": {}, 263 | "output_type": "execute_result" 264 | } 265 | ], 266 | "source": [ 267 | "fruits.pop()" 268 | ] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "execution_count": 74, 273 | "metadata": {}, 274 | "outputs": [ 275 | { 276 | "data": { 277 | "text/plain": [ 278 | "['apple', 'apple', 'apple', 'watermelon', 'grapes']" 279 | ] 280 | }, 281 | "execution_count": 74, 282 | "metadata": {}, 283 | "output_type": "execute_result" 284 | } 285 | ], 286 | "source": [ 287 | "fruits" 288 | ] 289 | }, 290 | { 291 | "cell_type": "code", 292 | "execution_count": 75, 293 | "metadata": {}, 294 | "outputs": [ 295 | { 296 | "data": { 297 | "text/plain": [ 298 | "'apple'" 299 | ] 300 | }, 301 | "execution_count": 75, 302 | "metadata": {}, 303 | "output_type": "execute_result" 304 | } 305 | ], 306 | "source": [ 307 | "fruits_set.pop()" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": 76, 313 | "metadata": {}, 314 | "outputs": [], 315 | "source": [ 316 | "fruits_set.clear()" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "execution_count": 78, 322 | "metadata": {}, 323 | "outputs": [ 324 | { 325 | "data": { 326 | "text/plain": [ 327 | "set()" 328 | ] 329 | }, 330 | "execution_count": 78, 331 | "metadata": {}, 332 | "output_type": "execute_result" 333 | } 334 | ], 335 | "source": [ 336 | "fruits_set" 337 | ] 338 | }, 339 | { 340 | "cell_type": "code", 341 | "execution_count": null, 342 | "metadata": {}, 343 | "outputs": [], 344 | "source": [] 345 | } 346 | ], 347 | "metadata": { 348 | "kernelspec": { 349 | "display_name": "Python 3", 350 | "language": "python", 351 | "name": "python3" 352 | }, 353 | "language_info": { 354 | "codemirror_mode": { 355 | "name": "ipython", 356 | "version": 3 357 | }, 358 | "file_extension": ".py", 359 | "mimetype": "text/x-python", 360 | "name": "python", 361 | "nbconvert_exporter": "python", 362 | "pygments_lexer": "ipython3", 363 | "version": "3.6.9" 364 | } 365 | }, 366 | "nbformat": 4, 367 | "nbformat_minor": 4 368 | } 369 | -------------------------------------------------------------------------------- /notebooks/23_set_operations.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #23\n", 8 | "\n", 9 | "## Set operations\n", 10 | "\n", 11 | "* Remember: we can do the same operations that we can do with mathematical sets." 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 56, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "fruits = [\"apple\", \"apple\", \"apple\", \"watermelon\", \"grapes\", \"grapes\", \"banana\"]" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 57, 26 | "metadata": {}, 27 | "outputs": [], 28 | "source": [ 29 | "fruits_set = set(fruits)" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 58, 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "another_fruits_set = {\"lemon\", \"pineapple\", \"mango\", \"peach\", \"grapes\", \"watermelon\", \"apple\"}" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 59, 44 | "metadata": {}, 45 | "outputs": [ 46 | { 47 | "data": { 48 | "text/plain": [ 49 | "{'apple', 'banana', 'grapes', 'watermelon'}" 50 | ] 51 | }, 52 | "execution_count": 59, 53 | "metadata": {}, 54 | "output_type": "execute_result" 55 | } 56 | ], 57 | "source": [ 58 | "fruits_set" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 60, 64 | "metadata": {}, 65 | "outputs": [ 66 | { 67 | "data": { 68 | "text/plain": [ 69 | "{'apple', 'grapes', 'lemon', 'mango', 'peach', 'pineapple', 'watermelon'}" 70 | ] 71 | }, 72 | "execution_count": 60, 73 | "metadata": {}, 74 | "output_type": "execute_result" 75 | } 76 | ], 77 | "source": [ 78 | "another_fruits_set" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": 61, 84 | "metadata": {}, 85 | "outputs": [ 86 | { 87 | "data": { 88 | "text/plain": [ 89 | "False" 90 | ] 91 | }, 92 | "execution_count": 61, 93 | "metadata": {}, 94 | "output_type": "execute_result" 95 | } 96 | ], 97 | "source": [ 98 | "another_fruits_set.issuperset(fruits_set)" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "## Union\n", 106 | "\n", 107 | "![union](https://www.xoax.net/math/ref/algebra/incl/set_operations/set_union.png)" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": 17, 113 | "metadata": {}, 114 | "outputs": [ 115 | { 116 | "data": { 117 | "text/plain": [ 118 | "{'apple', 'grapes', 'lemon', 'mango', 'peach', 'pineapple', 'watermelon'}" 119 | ] 120 | }, 121 | "execution_count": 17, 122 | "metadata": {}, 123 | "output_type": "execute_result" 124 | } 125 | ], 126 | "source": [ 127 | "fruits_set | another_fruits_set" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": 18, 133 | "metadata": {}, 134 | "outputs": [ 135 | { 136 | "data": { 137 | "text/plain": [ 138 | "{'apple', 'grapes', 'lemon', 'mango', 'peach', 'pineapple', 'watermelon'}" 139 | ] 140 | }, 141 | "execution_count": 18, 142 | "metadata": {}, 143 | "output_type": "execute_result" 144 | } 145 | ], 146 | "source": [ 147 | "fruits_set.union(another_fruits_set)" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": 19, 153 | "metadata": {}, 154 | "outputs": [ 155 | { 156 | "data": { 157 | "text/plain": [ 158 | "{'apple', 'grapes', 'watermelon'}" 159 | ] 160 | }, 161 | "execution_count": 19, 162 | "metadata": {}, 163 | "output_type": "execute_result" 164 | } 165 | ], 166 | "source": [ 167 | "fruits_set" 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": 20, 173 | "metadata": {}, 174 | "outputs": [ 175 | { 176 | "data": { 177 | "text/plain": [ 178 | "{'apple', 'grapes', 'lemon', 'mango', 'peach', 'pineapple', 'watermelon'}" 179 | ] 180 | }, 181 | "execution_count": 20, 182 | "metadata": {}, 183 | "output_type": "execute_result" 184 | } 185 | ], 186 | "source": [ 187 | "another_fruits_set" 188 | ] 189 | }, 190 | { 191 | "cell_type": "code", 192 | "execution_count": 23, 193 | "metadata": {}, 194 | "outputs": [], 195 | "source": [ 196 | "fruits_set.update(another_fruits_set)" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": 24, 202 | "metadata": {}, 203 | "outputs": [ 204 | { 205 | "data": { 206 | "text/plain": [ 207 | "{'apple', 'grapes', 'lemon', 'mango', 'peach', 'pineapple', 'watermelon'}" 208 | ] 209 | }, 210 | "execution_count": 24, 211 | "metadata": {}, 212 | "output_type": "execute_result" 213 | } 214 | ], 215 | "source": [ 216 | "fruits_set" 217 | ] 218 | }, 219 | { 220 | "cell_type": "markdown", 221 | "metadata": {}, 222 | "source": [ 223 | "## Intersection\n", 224 | "\n", 225 | "![intersection](https://www.thoughtco.com/thmb/5a6BbiGq6yyaPBtwEr7IZdvZdd4=/768x0/filters:no_upscale():max_bytes(150000):strip_icc()/intersection-57c632dd5f9b5855e5848ee8.jpg)" 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": 31, 231 | "metadata": {}, 232 | "outputs": [ 233 | { 234 | "data": { 235 | "text/plain": [ 236 | "{'apple', 'grapes', 'watermelon'}" 237 | ] 238 | }, 239 | "execution_count": 31, 240 | "metadata": {}, 241 | "output_type": "execute_result" 242 | } 243 | ], 244 | "source": [ 245 | "fruits_set & another_fruits_set" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": 32, 251 | "metadata": {}, 252 | "outputs": [ 253 | { 254 | "data": { 255 | "text/plain": [ 256 | "{'apple', 'grapes', 'watermelon'}" 257 | ] 258 | }, 259 | "execution_count": 32, 260 | "metadata": {}, 261 | "output_type": "execute_result" 262 | } 263 | ], 264 | "source": [ 265 | "fruits_set.intersection(another_fruits_set)" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": 38, 271 | "metadata": {}, 272 | "outputs": [ 273 | { 274 | "name": "stdout", 275 | "output_type": "stream", 276 | "text": [ 277 | "{'watermelon', 'grapes', 'banana', 'apple'}\n", 278 | "{'watermelon', 'lemon', 'pineapple', 'mango', 'peach', 'grapes', 'apple'}\n" 279 | ] 280 | } 281 | ], 282 | "source": [ 283 | "print(fruits_set)\n", 284 | "print(another_fruits_set)" 285 | ] 286 | }, 287 | { 288 | "cell_type": "code", 289 | "execution_count": 39, 290 | "metadata": {}, 291 | "outputs": [], 292 | "source": [ 293 | "fruits_set &= another_fruits_set" 294 | ] 295 | }, 296 | { 297 | "cell_type": "code", 298 | "execution_count": 41, 299 | "metadata": {}, 300 | "outputs": [], 301 | "source": [ 302 | "fruits_set.intersection_update(another_fruits_set)" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 42, 308 | "metadata": {}, 309 | "outputs": [ 310 | { 311 | "data": { 312 | "text/plain": [ 313 | "{'apple', 'grapes', 'watermelon'}" 314 | ] 315 | }, 316 | "execution_count": 42, 317 | "metadata": {}, 318 | "output_type": "execute_result" 319 | } 320 | ], 321 | "source": [ 322 | "fruits_set" 323 | ] 324 | }, 325 | { 326 | "cell_type": "markdown", 327 | "metadata": {}, 328 | "source": [ 329 | "## Difference\n", 330 | "\n", 331 | "![difference](https://s3.amazonaws.com/hr-challenge-images/9420/1437904659-11e4bef847-A-B.png)" 332 | ] 333 | }, 334 | { 335 | "cell_type": "code", 336 | "execution_count": 50, 337 | "metadata": {}, 338 | "outputs": [ 339 | { 340 | "data": { 341 | "text/plain": [ 342 | "{'banana'}" 343 | ] 344 | }, 345 | "execution_count": 50, 346 | "metadata": {}, 347 | "output_type": "execute_result" 348 | } 349 | ], 350 | "source": [ 351 | "fruits_set - another_fruits_set" 352 | ] 353 | }, 354 | { 355 | "cell_type": "code", 356 | "execution_count": 51, 357 | "metadata": {}, 358 | "outputs": [ 359 | { 360 | "data": { 361 | "text/plain": [ 362 | "{'banana'}" 363 | ] 364 | }, 365 | "execution_count": 51, 366 | "metadata": {}, 367 | "output_type": "execute_result" 368 | } 369 | ], 370 | "source": [ 371 | "fruits_set.difference(another_fruits_set)" 372 | ] 373 | }, 374 | { 375 | "cell_type": "code", 376 | "execution_count": 52, 377 | "metadata": {}, 378 | "outputs": [], 379 | "source": [ 380 | "fruits_set -= another_fruits_set" 381 | ] 382 | }, 383 | { 384 | "cell_type": "code", 385 | "execution_count": 53, 386 | "metadata": {}, 387 | "outputs": [ 388 | { 389 | "data": { 390 | "text/plain": [ 391 | "{'banana'}" 392 | ] 393 | }, 394 | "execution_count": 53, 395 | "metadata": {}, 396 | "output_type": "execute_result" 397 | } 398 | ], 399 | "source": [ 400 | "fruits_set" 401 | ] 402 | }, 403 | { 404 | "cell_type": "code", 405 | "execution_count": 54, 406 | "metadata": {}, 407 | "outputs": [], 408 | "source": [ 409 | "fruits_set.difference_update(another_fruits_set)" 410 | ] 411 | }, 412 | { 413 | "cell_type": "code", 414 | "execution_count": 55, 415 | "metadata": {}, 416 | "outputs": [ 417 | { 418 | "data": { 419 | "text/plain": [ 420 | "{'banana'}" 421 | ] 422 | }, 423 | "execution_count": 55, 424 | "metadata": {}, 425 | "output_type": "execute_result" 426 | } 427 | ], 428 | "source": [ 429 | "fruits_set" 430 | ] 431 | }, 432 | { 433 | "cell_type": "markdown", 434 | "metadata": {}, 435 | "source": [ 436 | "## Symmetric difference\n", 437 | "\n", 438 | "![symmetric](https://www.thoughtco.com/thmb/UbezhY2EuSWTwAjyarCIimGD03I=/768x0/filters:no_upscale():max_bytes(150000):strip_icc()/symmetric-56a8fa9f5f9b58b7d0f6ea14.jpg)" 439 | ] 440 | }, 441 | { 442 | "cell_type": "code", 443 | "execution_count": 62, 444 | "metadata": {}, 445 | "outputs": [ 446 | { 447 | "data": { 448 | "text/plain": [ 449 | "{'banana', 'lemon', 'mango', 'peach', 'pineapple'}" 450 | ] 451 | }, 452 | "execution_count": 62, 453 | "metadata": {}, 454 | "output_type": "execute_result" 455 | } 456 | ], 457 | "source": [ 458 | "fruits_set ^ another_fruits_set" 459 | ] 460 | }, 461 | { 462 | "cell_type": "code", 463 | "execution_count": 63, 464 | "metadata": {}, 465 | "outputs": [ 466 | { 467 | "data": { 468 | "text/plain": [ 469 | "{'banana', 'lemon', 'mango', 'peach', 'pineapple'}" 470 | ] 471 | }, 472 | "execution_count": 63, 473 | "metadata": {}, 474 | "output_type": "execute_result" 475 | } 476 | ], 477 | "source": [ 478 | "fruits_set.symmetric_difference(another_fruits_set)" 479 | ] 480 | }, 481 | { 482 | "cell_type": "code", 483 | "execution_count": 64, 484 | "metadata": {}, 485 | "outputs": [], 486 | "source": [ 487 | "fruits_set ^= another_fruits_set" 488 | ] 489 | }, 490 | { 491 | "cell_type": "code", 492 | "execution_count": 65, 493 | "metadata": {}, 494 | "outputs": [ 495 | { 496 | "data": { 497 | "text/plain": [ 498 | "{'banana', 'lemon', 'mango', 'peach', 'pineapple'}" 499 | ] 500 | }, 501 | "execution_count": 65, 502 | "metadata": {}, 503 | "output_type": "execute_result" 504 | } 505 | ], 506 | "source": [ 507 | "fruits_set" 508 | ] 509 | }, 510 | { 511 | "cell_type": "code", 512 | "execution_count": 66, 513 | "metadata": {}, 514 | "outputs": [], 515 | "source": [ 516 | "fruits_set.symmetric_difference_update(another_fruits_set)" 517 | ] 518 | }, 519 | { 520 | "cell_type": "code", 521 | "execution_count": 67, 522 | "metadata": {}, 523 | "outputs": [ 524 | { 525 | "data": { 526 | "text/plain": [ 527 | "{'apple', 'banana', 'grapes', 'watermelon'}" 528 | ] 529 | }, 530 | "execution_count": 67, 531 | "metadata": {}, 532 | "output_type": "execute_result" 533 | } 534 | ], 535 | "source": [ 536 | "fruits_set" 537 | ] 538 | }, 539 | { 540 | "cell_type": "code", 541 | "execution_count": null, 542 | "metadata": {}, 543 | "outputs": [], 544 | "source": [] 545 | } 546 | ], 547 | "metadata": { 548 | "kernelspec": { 549 | "display_name": "Python 3", 550 | "language": "python", 551 | "name": "python3" 552 | }, 553 | "language_info": { 554 | "codemirror_mode": { 555 | "name": "ipython", 556 | "version": 3 557 | }, 558 | "file_extension": ".py", 559 | "mimetype": "text/x-python", 560 | "name": "python", 561 | "nbconvert_exporter": "python", 562 | "pygments_lexer": "ipython3", 563 | "version": "3.6.9" 564 | } 565 | }, 566 | "nbformat": 4, 567 | "nbformat_minor": 4 568 | } 569 | -------------------------------------------------------------------------------- /notebooks/24_frozenset.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #24\n", 8 | "\n", 9 | "## Frozenset\n", 10 | "\n", 11 | "* The frozenset() method returns an immutable frozenset object initialized with elements from the given iterable.\n", 12 | "* Frozen set is just an immutable version of a Python set object. While elements of a set can be modified at any time, elements of frozen set remains the same after creation." 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 1, 18 | "metadata": {}, 19 | "outputs": [], 20 | "source": [ 21 | "empty_set = set()" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 2, 27 | "metadata": {}, 28 | "outputs": [ 29 | { 30 | "ename": "TypeError", 31 | "evalue": "unhashable type: 'dict'", 32 | "output_type": "error", 33 | "traceback": [ 34 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 35 | "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", 36 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mempty_set\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;34m\"apple\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m60\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"watermelon\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m50\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 37 | "\u001b[0;31mTypeError\u001b[0m: unhashable type: 'dict'" 38 | ] 39 | } 40 | ], 41 | "source": [ 42 | "empty_set.add({\"apple\": 60, \"watermelon\": 50})" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 6, 48 | "metadata": {}, 49 | "outputs": [ 50 | { 51 | "ename": "TypeError", 52 | "evalue": "unhashable type: 'set'", 53 | "output_type": "error", 54 | "traceback": [ 55 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 56 | "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", 57 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mempty_dictionary\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;36m11\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m7\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m6\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 58 | "\u001b[0;31mTypeError\u001b[0m: unhashable type: 'set'" 59 | ] 60 | } 61 | ], 62 | "source": [ 63 | "empty_dictionary = {{11,2,5,7}: 6}" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 7, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "empty_set = set()" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 8, 78 | "metadata": {}, 79 | "outputs": [ 80 | { 81 | "ename": "TypeError", 82 | "evalue": "unhashable type: 'set'", 83 | "output_type": "error", 84 | "traceback": [ 85 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 86 | "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", 87 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mempty_set\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m4\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 88 | "\u001b[0;31mTypeError\u001b[0m: unhashable type: 'set'" 89 | ] 90 | } 91 | ], 92 | "source": [ 93 | "empty_set.add({1,2,4})" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": 9, 99 | "metadata": {}, 100 | "outputs": [], 101 | "source": [ 102 | "frozen_set = frozenset([1,2,3,5,1,2,4])" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": 10, 108 | "metadata": {}, 109 | "outputs": [ 110 | { 111 | "data": { 112 | "text/plain": [ 113 | "frozenset({1, 2, 3, 4, 5})" 114 | ] 115 | }, 116 | "execution_count": 10, 117 | "metadata": {}, 118 | "output_type": "execute_result" 119 | } 120 | ], 121 | "source": [ 122 | "frozen_set" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 11, 128 | "metadata": {}, 129 | "outputs": [], 130 | "source": [ 131 | "empty_set.add(frozen_set)" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": 12, 137 | "metadata": {}, 138 | "outputs": [ 139 | { 140 | "data": { 141 | "text/plain": [ 142 | "{frozenset({1, 2, 3, 4, 5})}" 143 | ] 144 | }, 145 | "execution_count": 12, 146 | "metadata": {}, 147 | "output_type": "execute_result" 148 | } 149 | ], 150 | "source": [ 151 | "empty_set" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": 13, 157 | "metadata": {}, 158 | "outputs": [], 159 | "source": [ 160 | "empty_dictionary = {frozen_set: 6}" 161 | ] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "execution_count": 14, 166 | "metadata": {}, 167 | "outputs": [ 168 | { 169 | "data": { 170 | "text/plain": [ 171 | "{frozenset({1, 2, 3, 4, 5}): 6}" 172 | ] 173 | }, 174 | "execution_count": 14, 175 | "metadata": {}, 176 | "output_type": "execute_result" 177 | } 178 | ], 179 | "source": [ 180 | "empty_dictionary" 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "execution_count": null, 186 | "metadata": {}, 187 | "outputs": [], 188 | "source": [] 189 | } 190 | ], 191 | "metadata": { 192 | "kernelspec": { 193 | "display_name": "Python 3", 194 | "language": "python", 195 | "name": "python3" 196 | }, 197 | "language_info": { 198 | "codemirror_mode": { 199 | "name": "ipython", 200 | "version": 3 201 | }, 202 | "file_extension": ".py", 203 | "mimetype": "text/x-python", 204 | "name": "python", 205 | "nbconvert_exporter": "python", 206 | "pygments_lexer": "ipython3", 207 | "version": "3.6.9" 208 | } 209 | }, 210 | "nbformat": 4, 211 | "nbformat_minor": 4 212 | } 213 | -------------------------------------------------------------------------------- /notebooks/25_files_you_must_have.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #25\n", 8 | "\n", 9 | "## Files you must have in every project\n", 10 | "\n", 11 | "* The virtual environment \n", 12 | "* The `requirements.txt`\n", 13 | "* The `README.md`\n", 14 | "* The `.gitignore`" 15 | ] 16 | } 17 | ], 18 | "metadata": { 19 | "kernelspec": { 20 | "display_name": "Python 3", 21 | "language": "python", 22 | "name": "python3" 23 | }, 24 | "language_info": { 25 | "codemirror_mode": { 26 | "name": "ipython", 27 | "version": 3 28 | }, 29 | "file_extension": ".py", 30 | "mimetype": "text/x-python", 31 | "name": "python", 32 | "nbconvert_exporter": "python", 33 | "pygments_lexer": "ipython3", 34 | "version": "3.6.9" 35 | } 36 | }, 37 | "nbformat": 4, 38 | "nbformat_minor": 4 39 | } 40 | -------------------------------------------------------------------------------- /notebooks/26_python-dotenv.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #26\n", 8 | "\n", 9 | "## The python-dotenv \n", 10 | "\n", 11 | "* It helps to manage environment variables easily." 12 | ] 13 | } 14 | ], 15 | "metadata": { 16 | "kernelspec": { 17 | "display_name": "Python 3", 18 | "language": "python", 19 | "name": "python3" 20 | }, 21 | "language_info": { 22 | "codemirror_mode": { 23 | "name": "ipython", 24 | "version": 3 25 | }, 26 | "file_extension": ".py", 27 | "mimetype": "text/x-python", 28 | "name": "python", 29 | "nbconvert_exporter": "python", 30 | "pygments_lexer": "ipython3", 31 | "version": "3.6.9" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 4 36 | } 37 | -------------------------------------------------------------------------------- /notebooks/27_custom_exceptions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #27\n", 8 | "\n", 9 | "## Custom exceptions\n", 10 | "\n", 11 | "* We can define our own custom exceptions in Python.\n", 12 | "* We just need to inherit from the Exception class!" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 1, 18 | "metadata": {}, 19 | "outputs": [], 20 | "source": [ 21 | "import random" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 2, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "correct_number = random.randint(1, 10)" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 3, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "class NumberTooSmall(Exception):\n", 40 | " pass" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": 4, 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "class NUmberTooBig(Exception):\n", 50 | " pass" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 10, 56 | "metadata": {}, 57 | "outputs": [ 58 | { 59 | "name": "stdout", 60 | "output_type": "stream", 61 | "text": [ 62 | "Enter your number: 4\n", 63 | "The number you entered is too small\n", 64 | "Enter your number: 5\n", 65 | "The number you entered is too small\n", 66 | "Enter your number: 6\n", 67 | "The number you entered is too small\n", 68 | "Enter your number: 7\n", 69 | "The number you entered is too small\n", 70 | "Enter your number: 8\n", 71 | "The number you entered is too small\n", 72 | "Enter your number: 9\n", 73 | "You guessed the number!\n" 74 | ] 75 | } 76 | ], 77 | "source": [ 78 | "while True:\n", 79 | " try:\n", 80 | " n = int(input(\"Enter your number: \"))\n", 81 | " if n < correct_number:\n", 82 | " raise NumberTooSmall(\"The number you entered is too small\")\n", 83 | " elif n > correct_number:\n", 84 | " raise NumberTooBig(\"The number is too big\")\n", 85 | " else:\n", 86 | " print(\"You guessed the number!\")\n", 87 | " break\n", 88 | " except NumberTooSmall as error:\n", 89 | " print(error)\n", 90 | " except NumberTooBig as error:\n", 91 | " print(error)\n", 92 | " except ValueError:\n", 93 | " print(\"You did not entered a number\")\n", 94 | " " 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": null, 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [] 103 | } 104 | ], 105 | "metadata": { 106 | "kernelspec": { 107 | "display_name": "Python 3", 108 | "language": "python", 109 | "name": "python3" 110 | }, 111 | "language_info": { 112 | "codemirror_mode": { 113 | "name": "ipython", 114 | "version": 3 115 | }, 116 | "file_extension": ".py", 117 | "mimetype": "text/x-python", 118 | "name": "python", 119 | "nbconvert_exporter": "python", 120 | "pygments_lexer": "ipython3", 121 | "version": "3.6.9" 122 | } 123 | }, 124 | "nbformat": 4, 125 | "nbformat_minor": 4 126 | } 127 | -------------------------------------------------------------------------------- /notebooks/28_unit_testing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #28\n", 8 | "\n", 9 | "## Unit testing with pytest\n", 10 | "\n", 11 | "### TDD (Test driven development)\n", 12 | "\n", 13 | "![tdd](https://marsner.com/wp-content/uploads/test-driven-development-TDD.png)" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 6, 19 | "metadata": {}, 20 | "outputs": [ 21 | { 22 | "ename": "AssertionError", 23 | "evalue": "", 24 | "output_type": "error", 25 | "traceback": [ 26 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 27 | "\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)", 28 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32massert\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0;36m2\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m5\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 29 | "\u001b[0;31mAssertionError\u001b[0m: " 30 | ] 31 | } 32 | ], 33 | "source": [ 34 | "assert 2+2 == 5" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [] 43 | } 44 | ], 45 | "metadata": { 46 | "kernelspec": { 47 | "display_name": "Python 3", 48 | "language": "python", 49 | "name": "python3" 50 | }, 51 | "language_info": { 52 | "codemirror_mode": { 53 | "name": "ipython", 54 | "version": 3 55 | }, 56 | "file_extension": ".py", 57 | "mimetype": "text/x-python", 58 | "name": "python", 59 | "nbconvert_exporter": "python", 60 | "pygments_lexer": "ipython3", 61 | "version": "3.6.9" 62 | } 63 | }, 64 | "nbformat": 4, 65 | "nbformat_minor": 4 66 | } 67 | -------------------------------------------------------------------------------- /notebooks/29_fixtures.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #29\n", 8 | "\n", 9 | "## Fixtures\n", 10 | "\n", 11 | "* Test fixtures initialize test functions.\n", 12 | "* They provide a fixed baseline so that tests execute reliably and produce consistent, repeatable, results.\n", 13 | "* Initialization may setup services, state, or other operating environments.\n" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": null, 19 | "metadata": {}, 20 | "outputs": [], 21 | "source": [] 22 | } 23 | ], 24 | "metadata": { 25 | "kernelspec": { 26 | "display_name": "Python 3", 27 | "language": "python", 28 | "name": "python3" 29 | }, 30 | "language_info": { 31 | "codemirror_mode": { 32 | "name": "ipython", 33 | "version": 3 34 | }, 35 | "file_extension": ".py", 36 | "mimetype": "text/x-python", 37 | "name": "python", 38 | "nbconvert_exporter": "python", 39 | "pygments_lexer": "ipython3", 40 | "version": "3.6.9" 41 | } 42 | }, 43 | "nbformat": 4, 44 | "nbformat_minor": 4 45 | } 46 | -------------------------------------------------------------------------------- /notebooks/30_parametrized_tests.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learn Python by doing #30\n", 8 | "\n", 9 | "## Parametrized tests\n", 10 | "\n", 11 | "* The @pytest.mark.parametrize decorator allows us to pass several cases to one test.\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": null, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [] 20 | } 21 | ], 22 | "metadata": { 23 | "kernelspec": { 24 | "display_name": "Python 3", 25 | "language": "python", 26 | "name": "python3" 27 | }, 28 | "language_info": { 29 | "codemirror_mode": { 30 | "name": "ipython", 31 | "version": 3 32 | }, 33 | "file_extension": ".py", 34 | "mimetype": "text/x-python", 35 | "name": "python", 36 | "nbconvert_exporter": "python", 37 | "pygments_lexer": "ipython3", 38 | "version": "3.6.9" 39 | } 40 | }, 41 | "nbformat": 4, 42 | "nbformat_minor": 4 43 | } 44 | -------------------------------------------------------------------------------- /python.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidArmendariz/advanced-python-skills-course/72bd2d830502e3c09a94260ba35e8180e86de945/python.jpg -------------------------------------------------------------------------------- /solutions/solution_anagrams.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Anagrams\n", 8 | "\n", 9 | "You will write a function that receives a word and a list of words and stay with all of those words in the list that are anagrams of the word passed. \n", 10 | "``` \n", 11 | "Input:\n", 12 | "First argument: \"code\"\n", 13 | "Second argument: [\"code\", \"deco\", \"ecod\", \"first\", \"strif\", \"frist\"]\n", 14 | "Output:\n", 15 | "[\"code\", \"deco\", \"ecod\"]\n", 16 | "```" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "def find_anagrams(word, list_of_words):\n", 26 | " sorted_word = sorted(word)\n", 27 | " # code -> cdeo\n", 28 | " return list(filter(lambda x: sorted(x) == sorted_word, list_of_words))" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": 2, 34 | "metadata": {}, 35 | "outputs": [ 36 | { 37 | "data": { 38 | "text/plain": [ 39 | "['code', 'deco', 'ecod']" 40 | ] 41 | }, 42 | "execution_count": 2, 43 | "metadata": {}, 44 | "output_type": "execute_result" 45 | } 46 | ], 47 | "source": [ 48 | "find_anagrams(\"code\", [\"code\", \"deco\", \"ecod\", \"first\", \"strif\", \"frist\"])" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": null, 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [] 57 | } 58 | ], 59 | "metadata": { 60 | "kernelspec": { 61 | "display_name": "Python 3", 62 | "language": "python", 63 | "name": "python3" 64 | }, 65 | "language_info": { 66 | "codemirror_mode": { 67 | "name": "ipython", 68 | "version": 3 69 | }, 70 | "file_extension": ".py", 71 | "mimetype": "text/x-python", 72 | "name": "python", 73 | "nbconvert_exporter": "python", 74 | "pygments_lexer": "ipython3", 75 | "version": "3.8.2" 76 | } 77 | }, 78 | "nbformat": 4, 79 | "nbformat_minor": 4 80 | } 81 | -------------------------------------------------------------------------------- /solutions/solution_anagrams.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # # Anagrams 5 | # 6 | # You will write a function that receives a word and a list of words and stay with all of those words in the list that are anagrams of the word passed. 7 | # ``` 8 | # Input: 9 | # First argument: "code" 10 | # Second argument: ["code", "deco", "ecod", "first", "strif", "frist"] 11 | # Output: 12 | # ["code", "deco", "ecod"] 13 | # ``` 14 | 15 | # In[1]: 16 | 17 | 18 | def find_anagrams(word, list_of_words): 19 | sorted_word = sorted(word) 20 | # code -> cdeo 21 | return list(filter(lambda x: sorted(x) == sorted_word, list_of_words)) 22 | 23 | 24 | # In[2]: 25 | 26 | 27 | find_anagrams("code", ["code", "deco", "ecod", "first", "strif", "frist"]) 28 | 29 | 30 | # In[ ]: 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /solutions/solution_bank_accounts.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Bank Accounts\n", 8 | "\n", 9 | "In this exercise, we will be creating a BankAccount class.\n", 10 | "\n", 11 | "This class must have a constructor that receives an initial amount and set it to a property called balance. If you don't provide an initial amount, then you should set balance with zero. \n", 12 | "\n", 13 | "You should write a setter and a getter for this property.\n", 14 | "\n", 15 | "The setter should validate if the amount you pass is greater than or equal to zero. If it is negative, the balance should be setted to zero.\n", 16 | "\n", 17 | "Pretty easy!" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 1, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "class BankAccount:\n", 27 | " def __init__(self, initial_amount=0):\n", 28 | " self.balance = initial_amount\n", 29 | " @property\n", 30 | " def balance(self):\n", 31 | " return self._balance\n", 32 | " @balance.setter\n", 33 | " def balance(self, amount):\n", 34 | " if amount >= 0:\n", 35 | " self._balance = amount\n", 36 | " else:\n", 37 | " self._balance = 0" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 2, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "bank_account = BankAccount()" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 7, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "bank_account.balance = -60" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 8, 61 | "metadata": {}, 62 | "outputs": [ 63 | { 64 | "data": { 65 | "text/plain": [ 66 | "0" 67 | ] 68 | }, 69 | "execution_count": 8, 70 | "metadata": {}, 71 | "output_type": "execute_result" 72 | } 73 | ], 74 | "source": [ 75 | "bank_account.balance" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": null, 81 | "metadata": {}, 82 | "outputs": [], 83 | "source": [] 84 | } 85 | ], 86 | "metadata": { 87 | "kernelspec": { 88 | "display_name": "Python 3", 89 | "language": "python", 90 | "name": "python3" 91 | }, 92 | "language_info": { 93 | "codemirror_mode": { 94 | "name": "ipython", 95 | "version": 3 96 | }, 97 | "file_extension": ".py", 98 | "mimetype": "text/x-python", 99 | "name": "python", 100 | "nbconvert_exporter": "python", 101 | "pygments_lexer": "ipython3", 102 | "version": "3.8.2" 103 | } 104 | }, 105 | "nbformat": 4, 106 | "nbformat_minor": 4 107 | } 108 | -------------------------------------------------------------------------------- /solutions/solution_bank_accounts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # # Bank Accounts 5 | # 6 | # In this exercise, we will be creating a BankAccount class. 7 | # 8 | # This class must have a constructor that receives an initial amount and set it to a property called balance. If you don't provide an initial amount, then you should set balance with zero. 9 | # 10 | # You should write a setter and a getter for this property. 11 | # 12 | # The setter should validate if the amount you pass is greater than or equal to zero. If it is negative, the balance should be setted to zero. 13 | # 14 | # Pretty easy! 15 | 16 | # In[1]: 17 | 18 | 19 | class BankAccount: 20 | def __init__(self, initial_amount=0): 21 | self.balance = initial_amount 22 | @property 23 | def balance(self): 24 | return self._balance 25 | @balance.setter 26 | def balance(self, amount): 27 | if amount >= 0: 28 | self._balance = amount 29 | else: 30 | self._balance = 0 31 | 32 | 33 | # In[2]: 34 | 35 | 36 | bank_account = BankAccount() 37 | 38 | 39 | # In[7]: 40 | 41 | 42 | bank_account.balance = -60 43 | 44 | 45 | # In[8]: 46 | 47 | 48 | bank_account.balance 49 | 50 | 51 | # In[ ]: 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /solutions/solution_complement_of_a_set.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# The complement of a set\n", 8 | "\n", 9 | "When I teach operations of a set, some people ask: How can we find the complement of a set?\n", 10 | "\n", 11 | "Well, you can't.\n", 12 | "\n", 13 | "The complement of a set is everything not in the set, but part of the \"universal set\". Without a definition of the universal set, you can't really give a standard-library definition of the complement of a set.\n", 14 | "\n", 15 | "Thus, the purpose of this task is to define a function that calculates the complement of a set. Your function will receive two arguments: the universal set and the set you want to calculate its complement.\n", 16 | "\n", 17 | "If you can't calculate the complement (because the set is not a subset of the universal set), your function should return None." 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 7, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "A = {'a','e','i','o','u'}\n", 27 | "universal_set = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',\n", 28 | " 'r','s','t','u','v','w','x','y','z'}" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": 8, 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "def complement(universal_set, A):\n", 38 | " if A.issubset(universal_set):\n", 39 | " return universal_set - A\n", 40 | " else:\n", 41 | " return None" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 9, 47 | "metadata": {}, 48 | "outputs": [ 49 | { 50 | "data": { 51 | "text/plain": [ 52 | "{'b',\n", 53 | " 'c',\n", 54 | " 'd',\n", 55 | " 'f',\n", 56 | " 'g',\n", 57 | " 'h',\n", 58 | " 'j',\n", 59 | " 'k',\n", 60 | " 'l',\n", 61 | " 'm',\n", 62 | " 'n',\n", 63 | " 'p',\n", 64 | " 'q',\n", 65 | " 'r',\n", 66 | " 's',\n", 67 | " 't',\n", 68 | " 'v',\n", 69 | " 'w',\n", 70 | " 'x',\n", 71 | " 'y',\n", 72 | " 'z'}" 73 | ] 74 | }, 75 | "execution_count": 9, 76 | "metadata": {}, 77 | "output_type": "execute_result" 78 | } 79 | ], 80 | "source": [ 81 | "complement(universal_set, A)" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": null, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [] 90 | } 91 | ], 92 | "metadata": { 93 | "kernelspec": { 94 | "display_name": "Python 3", 95 | "language": "python", 96 | "name": "python3" 97 | }, 98 | "language_info": { 99 | "codemirror_mode": { 100 | "name": "ipython", 101 | "version": 3 102 | }, 103 | "file_extension": ".py", 104 | "mimetype": "text/x-python", 105 | "name": "python", 106 | "nbconvert_exporter": "python", 107 | "pygments_lexer": "ipython3", 108 | "version": "3.8.2" 109 | } 110 | }, 111 | "nbformat": 4, 112 | "nbformat_minor": 4 113 | } 114 | -------------------------------------------------------------------------------- /solutions/solution_complement_of_a_set.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # # The complement of a set 5 | # 6 | # When I teach operations of a set, some people ask: How can we find the complement of a set? 7 | # 8 | # Well, you can't. 9 | # 10 | # The complement of a set is everything not in the set, but part of the "universal set". Without a definition of the universal set, you can't really give a standard-library definition of the complement of a set. 11 | # 12 | # Thus, the purpose of this task is to define a function that calculates the complement of a set. Your function will receive two arguments: the universal set and the set you want to calculate its complement. 13 | # 14 | # If you can't calculate the complement (because the set is not a subset of the universal set), your function should return None. 15 | 16 | # In[7]: 17 | 18 | 19 | A = {'a','e','i','o','u'} 20 | universal_set = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q', 21 | 'r','s','t','u','v','w','x','y','z'} 22 | 23 | 24 | # In[8]: 25 | 26 | 27 | def complement(universal_set, A): 28 | if A.issubset(universal_set): 29 | return universal_set - A 30 | else: 31 | return None 32 | 33 | 34 | # In[9]: 35 | 36 | 37 | complement(universal_set, A) 38 | 39 | 40 | # In[ ]: 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /solutions/solution_fibonacci_numbers.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Fibonacci Numbers\n", 8 | "\n", 9 | "Let's apply what we learned about generators by creating the so famous Fibonacci sequence.\n", 10 | "\n", 11 | "You must create a generator that yields fibonacci numbers. This must be an infinite stream generator. Thus, the function won't receive any arguments. You should not use recursion.\n", 12 | "\n", 13 | "Instead, you should take advantage of the fact that generators \"remember\" the state of the function.\n", 14 | "\n", 15 | "Remember that the first element (index 0) is 0 and the second element (index 1) is 1." 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": 18, 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "def fibonacci_numbers():\n", 25 | " a = 0\n", 26 | " b = 1\n", 27 | " yield a\n", 28 | " yield b\n", 29 | " while True:\n", 30 | " c = a + b\n", 31 | " a, b = b, c\n", 32 | " yield b" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 19, 38 | "metadata": {}, 39 | "outputs": [], 40 | "source": [ 41 | "fib = fibonacci_numbers()" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 29, 47 | "metadata": {}, 48 | "outputs": [ 49 | { 50 | "data": { 51 | "text/plain": [ 52 | "34" 53 | ] 54 | }, 55 | "execution_count": 29, 56 | "metadata": {}, 57 | "output_type": "execute_result" 58 | } 59 | ], 60 | "source": [ 61 | "next(fib)" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": null, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [] 70 | } 71 | ], 72 | "metadata": { 73 | "kernelspec": { 74 | "display_name": "Python 3", 75 | "language": "python", 76 | "name": "python3" 77 | }, 78 | "language_info": { 79 | "codemirror_mode": { 80 | "name": "ipython", 81 | "version": 3 82 | }, 83 | "file_extension": ".py", 84 | "mimetype": "text/x-python", 85 | "name": "python", 86 | "nbconvert_exporter": "python", 87 | "pygments_lexer": "ipython3", 88 | "version": "3.8.2" 89 | } 90 | }, 91 | "nbformat": 4, 92 | "nbformat_minor": 4 93 | } 94 | -------------------------------------------------------------------------------- /solutions/solution_fibonacci_numbers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # # Fibonacci Numbers 5 | # 6 | # Let's apply what we learned about generators by creating the so famous Fibonacci sequence. 7 | # 8 | # You must create a generator that yields fibonacci numbers. This must be an infinite stream generator. Thus, the function won't receive any arguments. You should not use recursion. 9 | # 10 | # Instead, you should take advantage of the fact that generators "remember" the state of the function. 11 | # 12 | # Remember that the first element (index 0) is 0 and the second element (index 1) is 1. 13 | 14 | # In[18]: 15 | 16 | 17 | def fibonacci_numbers(): 18 | a = 0 19 | b = 1 20 | yield a 21 | yield b 22 | while True: 23 | c = a + b 24 | a, b = b, c 25 | yield b 26 | 27 | 28 | # In[19]: 29 | 30 | 31 | fib = fibonacci_numbers() 32 | 33 | 34 | # In[29]: 35 | 36 | 37 | next(fib) 38 | 39 | 40 | # In[ ]: 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /solutions/solution_grouping_the_elements_by_the_count.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Grouping the elements by the count\n", 8 | "\n", 9 | "So, we already know how to find the most common elements using the Counter class right? But what if two or more elements have the same count? Remember that the most_common() method returns a list of tuples. Instead of that, we want to return a dictionary where they keys are the counts and the values are lists that contain the elements with that count.\n", 10 | "\n", 11 | "Example:\n", 12 | "\n", 13 | "```\n", 14 | "Input data:\n", 15 | "[\"apple\", \"apple\", \"grapes\", \"grapes\", \"watermelon\"]\n", 16 | "Output:\n", 17 | "{2: [\"apple\", \"grapes\"], 1: [\"watermelon\"]}\n", 18 | "```\n" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 1, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "from collections import Counter" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 2, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "def find_counts(list_of_elements):\n", 37 | " counts = Counter(list_of_elements)\n", 38 | " result = dict()\n", 39 | " for element, count in counts.items():\n", 40 | " result[count] = result.setdefault(count, []) + [element]\n", 41 | " return result" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 3, 47 | "metadata": {}, 48 | "outputs": [ 49 | { 50 | "data": { 51 | "text/plain": [ 52 | "{2: ['apple', 'grapes'], 1: ['watermelon']}" 53 | ] 54 | }, 55 | "execution_count": 3, 56 | "metadata": {}, 57 | "output_type": "execute_result" 58 | } 59 | ], 60 | "source": [ 61 | "find_counts([\"apple\", \"apple\", \"grapes\", \"grapes\", \"watermelon\"])" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": null, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [] 70 | } 71 | ], 72 | "metadata": { 73 | "kernelspec": { 74 | "display_name": "Python 3", 75 | "language": "python", 76 | "name": "python3" 77 | }, 78 | "language_info": { 79 | "codemirror_mode": { 80 | "name": "ipython", 81 | "version": 3 82 | }, 83 | "file_extension": ".py", 84 | "mimetype": "text/x-python", 85 | "name": "python", 86 | "nbconvert_exporter": "python", 87 | "pygments_lexer": "ipython3", 88 | "version": "3.8.2" 89 | } 90 | }, 91 | "nbformat": 4, 92 | "nbformat_minor": 4 93 | } 94 | -------------------------------------------------------------------------------- /solutions/solution_grouping_the_elements_by_the_count.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # # Grouping the elements by the count 5 | # 6 | # So, we already know how to find the most common elements using the Counter class right? But what if two or more elements have the same count? Remember that the most_common() method returns a list of tuples. Instead of that, we want to return a dictionary where they keys are the counts and the values are lists that contain the elements with that count. 7 | # 8 | # Example: 9 | # 10 | # ``` 11 | # Input data: 12 | # ["apple", "apple", "grapes", "grapes", "watermelon"] 13 | # Output: 14 | # {2: ["apple", "grapes"], 1: ["watermelon"]} 15 | # ``` 16 | # 17 | 18 | # In[1]: 19 | 20 | 21 | from collections import Counter 22 | 23 | 24 | # In[2]: 25 | 26 | 27 | def find_counts(list_of_elements): 28 | counts = Counter(list_of_elements) 29 | result = dict() 30 | for element, count in counts.items(): 31 | result[count] = result.setdefault(count, []) + [element] 32 | return result 33 | 34 | 35 | # In[3]: 36 | 37 | 38 | find_counts(["apple", "apple", "grapes", "grapes", "watermelon"]) 39 | 40 | 41 | # In[ ]: 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /solutions/solution_have_you_seen_this_number_before.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Have you seen this number before?\n", 8 | "\n", 9 | "Write a function that receives as an argument a list of numbers. For each number, append to an empty list the word \"YES\" if this number was previously encountered in the sequence, or \"NO\" if it was not.\n", 10 | "\n", 11 | "Example:\n", 12 | "```\n", 13 | "Input data:\n", 14 | "[1,2,1,2,4,5]\n", 15 | "Output:\n", 16 | "[\"NO\", \"NO\", \"YES\", \"YES\", \"NO\", \"NO\"]\n", 17 | "```" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 1, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "def number_seen(list_of_numbers):\n", 27 | " result_set = set()\n", 28 | " result = []\n", 29 | " for x in list_of_numbers:\n", 30 | " if x not in result_set:\n", 31 | " result_set.add(x)\n", 32 | " result.append(\"NO\")\n", 33 | " else:\n", 34 | " result.append(\"YES\")\n", 35 | " return result" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 2, 41 | "metadata": {}, 42 | "outputs": [ 43 | { 44 | "data": { 45 | "text/plain": [ 46 | "['NO', 'NO', 'YES', 'YES', 'NO', 'NO']" 47 | ] 48 | }, 49 | "execution_count": 2, 50 | "metadata": {}, 51 | "output_type": "execute_result" 52 | } 53 | ], 54 | "source": [ 55 | "number_seen([1,2,1,2,4,5])" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": null, 61 | "metadata": {}, 62 | "outputs": [], 63 | "source": [] 64 | } 65 | ], 66 | "metadata": { 67 | "kernelspec": { 68 | "display_name": "Python 3", 69 | "language": "python", 70 | "name": "python3" 71 | }, 72 | "language_info": { 73 | "codemirror_mode": { 74 | "name": "ipython", 75 | "version": 3 76 | }, 77 | "file_extension": ".py", 78 | "mimetype": "text/x-python", 79 | "name": "python", 80 | "nbconvert_exporter": "python", 81 | "pygments_lexer": "ipython3", 82 | "version": "3.8.2" 83 | } 84 | }, 85 | "nbformat": 4, 86 | "nbformat_minor": 4 87 | } 88 | -------------------------------------------------------------------------------- /solutions/solution_have_you_seen_this_number_before.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # # Have you seen this number before? 5 | # 6 | # Write a function that receives as an argument a list of numbers. For each number, append to an empty list the word "YES" if this number was previously encountered in the sequence, or "NO" if it was not. 7 | # 8 | # Example: 9 | # ``` 10 | # Input data: 11 | # [1,2,1,2,4,5] 12 | # Output: 13 | # ["NO", "NO", "YES", "YES", "NO", "NO"] 14 | # ``` 15 | 16 | # In[1]: 17 | 18 | 19 | def number_seen(list_of_numbers): 20 | result_set = set() 21 | result = [] 22 | for x in list_of_numbers: 23 | if x not in result_set: 24 | result_set.add(x) 25 | result.append("NO") 26 | else: 27 | result.append("YES") 28 | return result 29 | 30 | 31 | # In[2]: 32 | 33 | 34 | number_seen([1,2,1,2,4,5]) 35 | 36 | 37 | # In[ ]: 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /solutions/solution_implementing_xor.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# XOR\n", 8 | "\n", 9 | "XOR (exclusive or) is a boolean operator with the following truth table:\n", 10 | "\n", 11 | "``` \n", 12 | "XOR(0,0) = 0\n", 13 | "\n", 14 | "XOR(0,1) = 1\n", 15 | "\n", 16 | "XOR(1,0) = 1\n", 17 | "\n", 18 | "XOR(1,1) = 0\n", 19 | "```\n", 20 | "\n", 21 | "You must write a function that receives two lists as the arguments. These lists must consist of zeros and ones. Let's call them A and B.\n", 22 | "\n", 23 | "The function should return a list where the i-th element is `XOR(A[i], B[i])`.\n", 24 | "\n", 25 | "Example:\n", 26 | "\n", 27 | "``` \n", 28 | "Input data:\n", 29 | "First argument: [0, 0, 1, 1]\n", 30 | "Second argument: [0, 1, 0, 1]\n", 31 | "Output:\n", 32 | "[0, 1, 1, 0]\n", 33 | "```\n", 34 | "Please, use the map and zip functions." 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 3, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "def xor(A, B):\n", 44 | " return list(map(lambda x: x[0] ^ x[1], zip(A, B)))" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 4, 50 | "metadata": {}, 51 | "outputs": [ 52 | { 53 | "data": { 54 | "text/plain": [ 55 | "[0, 1, 1, 0]" 56 | ] 57 | }, 58 | "execution_count": 4, 59 | "metadata": {}, 60 | "output_type": "execute_result" 61 | } 62 | ], 63 | "source": [ 64 | "xor([0,0,1,1], [0,1,0,1])" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 5, 70 | "metadata": {}, 71 | "outputs": [ 72 | { 73 | "data": { 74 | "text/plain": [ 75 | "[0, 0, 1, 0]" 76 | ] 77 | }, 78 | "execution_count": 5, 79 | "metadata": {}, 80 | "output_type": "execute_result" 81 | } 82 | ], 83 | "source": [ 84 | "xor([1,0,1,1], [1,0,0,1])" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": null, 90 | "metadata": {}, 91 | "outputs": [], 92 | "source": [] 93 | } 94 | ], 95 | "metadata": { 96 | "kernelspec": { 97 | "display_name": "Python 3", 98 | "language": "python", 99 | "name": "python3" 100 | }, 101 | "language_info": { 102 | "codemirror_mode": { 103 | "name": "ipython", 104 | "version": 3 105 | }, 106 | "file_extension": ".py", 107 | "mimetype": "text/x-python", 108 | "name": "python", 109 | "nbconvert_exporter": "python", 110 | "pygments_lexer": "ipython3", 111 | "version": "3.8.2" 112 | } 113 | }, 114 | "nbformat": 4, 115 | "nbformat_minor": 4 116 | } 117 | -------------------------------------------------------------------------------- /solutions/solution_implementing_xor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # # XOR 5 | # 6 | # XOR (exclusive or) is a boolean operator with the following truth table: 7 | # 8 | # ``` 9 | # XOR(0,0) = 0 10 | # 11 | # XOR(0,1) = 1 12 | # 13 | # XOR(1,0) = 1 14 | # 15 | # XOR(1,1) = 0 16 | # ``` 17 | # 18 | # You must write a function that receives two lists as the arguments. These lists must consist of zeros and ones. Let's call them A and B. 19 | # 20 | # The function should return a list where the i-th element is `XOR(A[i], B[i])`. 21 | # 22 | # Example: 23 | # 24 | # ``` 25 | # Input data: 26 | # First argument: [0, 0, 1, 1] 27 | # Second argument: [0, 1, 0, 1] 28 | # Output: 29 | # [0, 1, 1, 0] 30 | # ``` 31 | # Please, use the map and zip functions. 32 | 33 | # In[3]: 34 | 35 | 36 | def xor(A, B): 37 | return list(map(lambda x: x[0] ^ x[1], zip(A, B))) 38 | 39 | 40 | # In[4]: 41 | 42 | 43 | xor([0,0,1,1], [0,1,0,1]) 44 | 45 | 46 | # In[5]: 47 | 48 | 49 | xor([1,0,1,1], [1,0,0,1]) 50 | 51 | 52 | # In[ ]: 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /solutions/solution_learning_the_words_in_a_strange_order.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Learning the words in a strange order\n", 8 | "\n", 9 | "One of your friends wants to learn new English words, but wants to do it in a certain order. \n", 10 | "\n", 11 | "- First, he chooses short words\n", 12 | "\n", 13 | "- If the words are the same length, he chooses them in lexicographical order when reading from right to left (he is Arab!). \n", 14 | "\n", 15 | "Write a function that receives a list of words, and returns a list in the order specified.\n", 16 | "\n", 17 | "Here is an example:\n", 18 | "\n", 19 | "``` \n", 20 | "Input data:\n", 21 | "[\"west\", \"tax\", \"size\", \"sea\", \"use\", \"think\", \"yard\", \"word\", \"town\"]\n", 22 | "\n", 23 | "Program output:\n", 24 | "[\"sea\", \"use\", \"tax\", \"yard\", \"word\", \"size\", \"town\", \"west\", \"think\"]\n", 25 | "```" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 20, 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "def learning_words(list_of_words):\n", 35 | " words = dict()\n", 36 | " # words = {4: [\"west\", \"size\", \"yard\", \"word\", \"town\"], 3: [\"tax\", \"sea\", \"use\"], 5: [\"think\"]}\n", 37 | " result = []\n", 38 | " for word in list_of_words:\n", 39 | " length = len(word)\n", 40 | " words[length] = words.get(length, []) + [word]\n", 41 | " for length in sorted(words):\n", 42 | " # length = 3\n", 43 | " # words[length] = [\"tax\", \"sea\", \"use\"]\n", 44 | " # -> [\"xat\", \"aes\", \"esu\"]\n", 45 | " # -> [\"aes\", \"esu\", \"xat\"]\n", 46 | " # -> [\"sea\", \"use\", \"tax\"]\n", 47 | " for word in sorted([x[::-1] for x in words[length]]):\n", 48 | " result.append(word[::-1])\n", 49 | " return result" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 21, 55 | "metadata": {}, 56 | "outputs": [ 57 | { 58 | "data": { 59 | "text/plain": [ 60 | "['sea', 'use', 'tax', 'yard', 'word', 'size', 'town', 'west', 'think']" 61 | ] 62 | }, 63 | "execution_count": 21, 64 | "metadata": {}, 65 | "output_type": "execute_result" 66 | } 67 | ], 68 | "source": [ 69 | "learning_words([\"west\", \"tax\", \"size\", \"sea\", \"use\", \"think\", \"yard\", \"word\", \"town\"])" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": null, 75 | "metadata": {}, 76 | "outputs": [], 77 | "source": [] 78 | } 79 | ], 80 | "metadata": { 81 | "kernelspec": { 82 | "display_name": "Python 3", 83 | "language": "python", 84 | "name": "python3" 85 | }, 86 | "language_info": { 87 | "codemirror_mode": { 88 | "name": "ipython", 89 | "version": 3 90 | }, 91 | "file_extension": ".py", 92 | "mimetype": "text/x-python", 93 | "name": "python", 94 | "nbconvert_exporter": "python", 95 | "pygments_lexer": "ipython3", 96 | "version": "3.8.2" 97 | } 98 | }, 99 | "nbformat": 4, 100 | "nbformat_minor": 4 101 | } 102 | -------------------------------------------------------------------------------- /solutions/solution_learning_the_words_in_a_strange_order.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # # Learning the words in a strange order 5 | # 6 | # One of your friends wants to learn new English words, but wants to do it in a certain order. 7 | # 8 | # - First, he chooses short words 9 | # 10 | # - If the words are the same length, he chooses them in lexicographical order when reading from right to left (he is Arab!). 11 | # 12 | # Write a function that receives a list of words, and returns a list in the order specified. 13 | # 14 | # Here is an example: 15 | # 16 | # ``` 17 | # Input data: 18 | # ["west", "tax", "size", "sea", "use", "think", "yard", "word", "town"] 19 | # 20 | # Program output: 21 | # ["sea", "use", "tax", "yard", "word", "size", "town", "west", "think"] 22 | # ``` 23 | 24 | # In[20]: 25 | 26 | 27 | def learning_words(list_of_words): 28 | words = dict() 29 | # words = {4: ["west", "size", "yard", "word", "town"], 3: ["tax", "sea", "use"], 5: ["think"]} 30 | result = [] 31 | for word in list_of_words: 32 | length = len(word) 33 | words[length] = words.get(length, []) + [word] 34 | for length in sorted(words): 35 | # length = 3 36 | # words[length] = ["tax", "sea", "use"] 37 | # -> ["xat", "aes", "esu"] 38 | # -> ["aes", "esu", "xat"] 39 | # -> ["sea", "use", "tax"] 40 | for word in sorted([x[::-1] for x in words[length]]): 41 | result.append(word[::-1]) 42 | return result 43 | 44 | 45 | # In[21]: 46 | 47 | 48 | learning_words(["west", "tax", "size", "sea", "use", "think", "yard", "word", "town"]) 49 | 50 | 51 | # In[ ]: 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /solutions/solution_prime_numbers.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Prime numbers\n", 8 | "\n", 9 | "Write an infinite generator that yields prime numbers.\n", 10 | "\n", 11 | "This is one of those generators that you have to be very careful about. Checking if a number is prime or not is a really expensive task. In fact, all of the cryptography and security over the Internet relies on this fact. If it weren't like this, then surely your bank account would have been compromised long time ago!\n", 12 | "\n", 13 | "Your task here is to write a generator that generates prime numbers, and that is what is going to be evaluated. But as a bonus do the following:\n", 14 | "\n", 15 | "Modify the generator so that it yields not only the next prime number, but also the time that it took to find that prime number.\n", 16 | "\n", 17 | "Make a scatter plot (maybe using matplotlib) where the x-axis consists of the prime numbers and the y-axis is the value it took to find that prime number." 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 55, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "import time" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 56, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "def prime_numbers():\n", 36 | " n = 2\n", 37 | " yield (n, 0)\n", 38 | " while True:\n", 39 | " start_time = time.time()\n", 40 | " n += 1\n", 41 | " is_prime = True\n", 42 | " for i in range(2, n):\n", 43 | " if n % i == 0:\n", 44 | " is_prime = False\n", 45 | " break\n", 46 | " if is_prime:\n", 47 | " end_time = time.time() - start_time\n", 48 | " yield (n, end_time)" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 57, 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "import matplotlib.pyplot as plt" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 58, 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "x = []\n", 67 | "y = []" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 59, 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [ 76 | "prime_numbers = prime_numbers()" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 60, 82 | "metadata": {}, 83 | "outputs": [], 84 | "source": [ 85 | "for i in range(1000):\n", 86 | " result = next(prime_numbers)\n", 87 | " x.append(result[0])\n", 88 | " y.append(result[1])" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 61, 94 | "metadata": {}, 95 | "outputs": [ 96 | { 97 | "data": { 98 | "text/plain": [ 99 | "Text(0, 0.5, 'Time in seconds')" 100 | ] 101 | }, 102 | "execution_count": 61, 103 | "metadata": {}, 104 | "output_type": "execute_result" 105 | }, 106 | { 107 | "data": { 108 | "image/png": "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\n", 109 | "text/plain": [ 110 | "
" 111 | ] 112 | }, 113 | "metadata": { 114 | "needs_background": "light" 115 | }, 116 | "output_type": "display_data" 117 | } 118 | ], 119 | "source": [ 120 | "plt.plot(x,y)\n", 121 | "plt.title(\"Time taken to calculate prime numbers\")\n", 122 | "plt.xlabel(\"Prime numbers\")\n", 123 | "plt.ylabel(\"Time in seconds\")" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": null, 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [] 132 | } 133 | ], 134 | "metadata": { 135 | "kernelspec": { 136 | "display_name": "Python 3", 137 | "language": "python", 138 | "name": "python3" 139 | }, 140 | "language_info": { 141 | "codemirror_mode": { 142 | "name": "ipython", 143 | "version": 3 144 | }, 145 | "file_extension": ".py", 146 | "mimetype": "text/x-python", 147 | "name": "python", 148 | "nbconvert_exporter": "python", 149 | "pygments_lexer": "ipython3", 150 | "version": "3.8.2" 151 | } 152 | }, 153 | "nbformat": 4, 154 | "nbformat_minor": 4 155 | } 156 | -------------------------------------------------------------------------------- /solutions/solution_prime_numbers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # # Prime numbers 5 | # 6 | # Write an infinite generator that yields prime numbers. 7 | # 8 | # This is one of those generators that you have to be very careful about. Checking if a number is prime or not is a really expensive task. In fact, all of the cryptography and security over the Internet relies on this fact. If it weren't like this, then surely your bank account would have been compromised long time ago! 9 | # 10 | # Your task here is to write a generator that generates prime numbers, and that is what is going to be evaluated. But as a bonus do the following: 11 | # 12 | # Modify the generator so that it yields not only the next prime number, but also the time that it took to find that prime number. 13 | # 14 | # Make a scatter plot (maybe using matplotlib) where the x-axis consists of the prime numbers and the y-axis is the value it took to find that prime number. 15 | 16 | # In[55]: 17 | 18 | 19 | import time 20 | 21 | 22 | # In[56]: 23 | 24 | 25 | def prime_numbers(): 26 | n = 2 27 | yield (n, 0) 28 | while True: 29 | start_time = time.time() 30 | n += 1 31 | is_prime = True 32 | for i in range(2, n): 33 | if n % i == 0: 34 | is_prime = False 35 | break 36 | if is_prime: 37 | end_time = time.time() - start_time 38 | yield (n, end_time) 39 | 40 | 41 | # In[57]: 42 | 43 | 44 | import matplotlib.pyplot as plt 45 | 46 | 47 | # In[58]: 48 | 49 | 50 | x = [] 51 | y = [] 52 | 53 | 54 | # In[59]: 55 | 56 | 57 | prime_numbers = prime_numbers() 58 | 59 | 60 | # In[60]: 61 | 62 | 63 | for i in range(1000): 64 | result = next(prime_numbers) 65 | x.append(result[0]) 66 | y.append(result[1]) 67 | 68 | 69 | # In[61]: 70 | 71 | 72 | plt.plot(x,y) 73 | plt.title("Time taken to calculate prime numbers") 74 | plt.xlabel("Prime numbers") 75 | plt.ylabel("Time in seconds") 76 | 77 | 78 | # In[ ]: 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /solutions/solution_summing_numbers_like_in_school.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Solution to exercise \"Summing numbers like in school\"" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 21, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "from itertools import zip_longest" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 22, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "# number_1: 1564\n", 26 | "# number_2: 587\n", 27 | "# 1564\n", 28 | "# +0587\n", 29 | "# -----\n", 30 | "# 2151" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 28, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "def sum_like_in_school(number_1, number_2, base=10):\n", 40 | " digits_zipped = zip_longest(reversed(str(number_1)), reversed(str(number_2)), fillvalue = 0)\n", 41 | " carry = 0\n", 42 | " result = \"\"\n", 43 | " for digit_1, digit_2 in digits_zipped:\n", 44 | " sum_of_two_digits = int(digit_1) + int(digit_2) + carry\n", 45 | " if sum_of_two_digits >= base:\n", 46 | " carry = 1\n", 47 | " result = str(sum_of_two_digits % base) + result\n", 48 | " else:\n", 49 | " carry = 0\n", 50 | " result = str(sum_of_two_digits) + result\n", 51 | " return int(result)" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": 35, 57 | "metadata": {}, 58 | "outputs": [ 59 | { 60 | "data": { 61 | "text/plain": [ 62 | "2040" 63 | ] 64 | }, 65 | "execution_count": 35, 66 | "metadata": {}, 67 | "output_type": "execute_result" 68 | } 69 | ], 70 | "source": [ 71 | "sum_like_in_school(1564, 587, 11)" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": null, 77 | "metadata": {}, 78 | "outputs": [], 79 | "source": [] 80 | } 81 | ], 82 | "metadata": { 83 | "kernelspec": { 84 | "display_name": "Python 3", 85 | "language": "python", 86 | "name": "python3" 87 | }, 88 | "language_info": { 89 | "codemirror_mode": { 90 | "name": "ipython", 91 | "version": 3 92 | }, 93 | "file_extension": ".py", 94 | "mimetype": "text/x-python", 95 | "name": "python", 96 | "nbconvert_exporter": "python", 97 | "pygments_lexer": "ipython3", 98 | "version": "3.8.2" 99 | } 100 | }, 101 | "nbformat": 4, 102 | "nbformat_minor": 4 103 | } 104 | -------------------------------------------------------------------------------- /solutions/solution_summing_numbers_like_in_school.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # ## Solution to exercise "Summing numbers like in school" 5 | 6 | # In[21]: 7 | 8 | 9 | from itertools import zip_longest 10 | 11 | 12 | # In[22]: 13 | 14 | 15 | # number_1: 1564 16 | # number_2: 587 17 | # 1564 18 | # +0587 19 | # ----- 20 | # 2151 21 | 22 | 23 | # In[28]: 24 | 25 | 26 | def sum_like_in_school(number_1, number_2, base=10): 27 | digits_zipped = zip_longest(reversed(str(number_1)), reversed(str(number_2)), fillvalue = 0) 28 | carry = 0 29 | result = "" 30 | for digit_1, digit_2 in digits_zipped: 31 | sum_of_two_digits = int(digit_1) + int(digit_2) + carry 32 | if sum_of_two_digits >= base: 33 | carry = 1 34 | result = str(sum_of_two_digits % base) + result 35 | else: 36 | carry = 0 37 | result = str(sum_of_two_digits) + result 38 | return int(result) 39 | 40 | 41 | # In[35]: 42 | 43 | 44 | sum_like_in_school(1564, 587, 11) 45 | 46 | 47 | # In[ ]: 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /solutions/solution_transforming_data.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Transforming data formats\n", 8 | "\n", 9 | "The reduce function is extremely useful to transform data structures. When I say data structure, I am not talking about queues, linked lists and all of those things. I am talking about how a dataset is presented (or structured). For example, suppose we have a list of dictionaries like this:\n", 10 | "\n", 11 | "```\n", 12 | "invitees = [{\"email\": \"alex@example.com\", \"name\": \"Alex\", \"status\": \"attending\"},\n", 13 | "{\"email\": \"brian@example.com\", \"name\": \"Brian\", \"status\": \"declined\"},\n", 14 | "{\"email\": \"carol@example.com\", \"name\": \"Carol\", \"status\": \"pending\"},\n", 15 | "{\"email\": \"david@example.com\", \"name\": \"David\", \"status\": \"attending\"},\n", 16 | "{\"email\": \"maria@example.com\", \"name\": \"Maria\", \"status\": \"attending\"}]\n", 17 | "```\n", 18 | "\n", 19 | "You want to transform this list of dictionaries to a single dictionary like this:\n", 20 | "\n", 21 | "```\n", 22 | "{\"alex@example.com\": \"attending\",\n", 23 | "\"brian@example.com\": \"declined\",\n", 24 | "\"carol@example.com\": \"pending\",\n", 25 | "\"david@example.com\": \"attending\",\n", 26 | "\"maria@example.com\": \"attending\"}\n", 27 | "```\n", 28 | "\n", 29 | "Here, the reduce function can help. You just have to write an adequate function (maybe using a lambda function won't work here) and pass it to the reduce function, along with the invitees list and an empty dictionary as the initializer.\n", 30 | "\n", 31 | "Give it a try!" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 14, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "from functools import reduce" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": 15, 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "def transform_invitees_data(invitees):\n", 50 | " def transform_data(acc, invitee):\n", 51 | " acc[invitee[\"email\"]] = invitee[\"status\"]\n", 52 | " return acc\n", 53 | " results = reduce(transform_data, invitees, {})\n", 54 | " return results" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 16, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "invitees = [{\"email\": \"alex@example.com\", \"name\": \"Alex\", \"status\": \"attending\"},\n", 64 | "{\"email\": \"brian@example.com\", \"name\": \"Brian\", \"status\": \"declined\"},\n", 65 | "{\"email\": \"carol@example.com\", \"name\": \"Carol\", \"status\": \"pending\"},\n", 66 | "{\"email\": \"david@example.com\", \"name\": \"David\", \"status\": \"attending\"},\n", 67 | "{\"email\": \"maria@example.com\", \"name\": \"Maria\", \"status\": \"attending\"}]" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 17, 73 | "metadata": {}, 74 | "outputs": [ 75 | { 76 | "data": { 77 | "text/plain": [ 78 | "{'alex@example.com': 'attending',\n", 79 | " 'brian@example.com': 'declined',\n", 80 | " 'carol@example.com': 'pending',\n", 81 | " 'david@example.com': 'attending',\n", 82 | " 'maria@example.com': 'attending'}" 83 | ] 84 | }, 85 | "execution_count": 17, 86 | "metadata": {}, 87 | "output_type": "execute_result" 88 | } 89 | ], 90 | "source": [ 91 | "transform_invitees_data(invitees)" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": {}, 98 | "outputs": [], 99 | "source": [] 100 | } 101 | ], 102 | "metadata": { 103 | "kernelspec": { 104 | "display_name": "Python 3", 105 | "language": "python", 106 | "name": "python3" 107 | }, 108 | "language_info": { 109 | "codemirror_mode": { 110 | "name": "ipython", 111 | "version": 3 112 | }, 113 | "file_extension": ".py", 114 | "mimetype": "text/x-python", 115 | "name": "python", 116 | "nbconvert_exporter": "python", 117 | "pygments_lexer": "ipython3", 118 | "version": "3.8.2" 119 | } 120 | }, 121 | "nbformat": 4, 122 | "nbformat_minor": 4 123 | } 124 | -------------------------------------------------------------------------------- /solutions/solution_transforming_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # # Transforming data formats 5 | # 6 | # The reduce function is extremely useful to transform data structures. When I say data structure, I am not talking about queues, linked lists and all of those things. I am talking about how a dataset is presented (or structured). For example, suppose we have a list of dictionaries like this: 7 | # 8 | # ``` 9 | # invitees = [{"email": "alex@example.com", "name": "Alex", "status": "attending"}, 10 | # {"email": "brian@example.com", "name": "Brian", "status": "declined"}, 11 | # {"email": "carol@example.com", "name": "Carol", "status": "pending"}, 12 | # {"email": "david@example.com", "name": "David", "status": "attending"}, 13 | # {"email": "maria@example.com", "name": "Maria", "status": "attending"}] 14 | # ``` 15 | # 16 | # You want to transform this list of dictionaries to a single dictionary like this: 17 | # 18 | # ``` 19 | # {"alex@example.com": "attending", 20 | # "brian@example.com": "declined", 21 | # "carol@example.com": "pending", 22 | # "david@example.com": "attending", 23 | # "maria@example.com": "attending"} 24 | # ``` 25 | # 26 | # Here, the reduce function can help. You just have to write an adequate function (maybe using a lambda function won't work here) and pass it to the reduce function, along with the invitees list and an empty dictionary as the initializer. 27 | # 28 | # Give it a try! 29 | 30 | # In[14]: 31 | 32 | 33 | from functools import reduce 34 | 35 | 36 | # In[15]: 37 | 38 | 39 | def transform_invitees_data(invitees): 40 | def transform_data(acc, invitee): 41 | acc[invitee["email"]] = invitee["status"] 42 | return acc 43 | results = reduce(transform_data, invitees, {}) 44 | return results 45 | 46 | 47 | # In[16]: 48 | 49 | 50 | invitees = [{"email": "alex@example.com", "name": "Alex", "status": "attending"}, 51 | {"email": "brian@example.com", "name": "Brian", "status": "declined"}, 52 | {"email": "carol@example.com", "name": "Carol", "status": "pending"}, 53 | {"email": "david@example.com", "name": "David", "status": "attending"}, 54 | {"email": "maria@example.com", "name": "Maria", "status": "attending"}] 55 | 56 | 57 | # In[17]: 58 | 59 | 60 | transform_invitees_data(invitees) 61 | 62 | 63 | # In[ ]: 64 | 65 | 66 | 67 | 68 | --------------------------------------------------------------------------------