Restructure *.ipynb files

- split review and exercises into files on their own
- update the contents overviews to include links to
  reviews and exercises
This commit is contained in:
Alexander Hess 2020-01-28 10:48:37 +01:00
parent 8af0280271
commit e24cf31104
28 changed files with 4335 additions and 3603 deletions

View file

@ -152,9 +152,9 @@
}
},
"source": [
"To \"read\" this book in the most meaningful way, a working installation of **Python 3.6** or higher is needed.\n",
"To \"read\" this book in the most meaningful way, a working installation of **Python 3.7** or higher is expected.\n",
"\n",
"A popular and beginner-friendly way is to install the [Anaconda Distribution](https://www.anaconda.com/distribution/) that not only ships Python and the standard library but comes pre-packaged with a lot of third-party libraries from the so-called \"scientific stack.\" Just go to the [download](https://www.anaconda.com/download/) page and install the latest version (i.e., *2019-07* with Python 3.7 at the time of this writing) for your operating system.\n",
"A popular and beginner-friendly way is to install the [Anaconda Distribution](https://www.anaconda.com/distribution/) that not only ships Python and the standard library but comes pre-packaged with a lot of third-party libraries from the so-called \"scientific stack.\" Just go to the [download](https://www.anaconda.com/download/) page and install the latest version (i.e., *2019-10* with Python 3.7 at the time of this writing) for your operating system.\n",
"\n",
"Then, among others, you find an entry \"Jupyter Notebook\" in your start menu like below. Click on it to open a new tab in your web browser where you can switch between folders as you could in your computer's default file browser."
]
@ -330,7 +330,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Python 3.7.3\r\n"
"Python 3.7.4\n"
]
}
],
@ -649,7 +649,7 @@
}
},
"source": [
"Even popular news and media outlets notice the recent popularity of Python: [Economist](https://www.economist.com/graphic-detail/2018/07/26/python-is-becoming-the-worlds-most-popular-coding-language), [Huffington Post](https://www.huffingtonpost.com/entry/why-python-is-the-best-programming-language-with-which_us_59ef8f62e4b04809c05011b9), [TechRepublic](https://www.techrepublic.com/article/why-python-is-so-popular-with-developers-3-reasons-the-language-has-exploded/), and [QZ](https://qz.com/1408660/the-rise-of-python-as-seen-through-a-decade-of-stack-overflow/)."
"[IEEE Sprectrum](https://spectrum.ieee.org/computing/software/the-top-programming-languages-2019) provides a more recent comparison of programming language's popularity. Even news and media outlets notice the recent popularity of Python: [Economist](https://www.economist.com/graphic-detail/2018/07/26/python-is-becoming-the-worlds-most-popular-coding-language), [Huffington Post](https://www.huffingtonpost.com/entry/why-python-is-the-best-programming-language-with-which_us_59ef8f62e4b04809c05011b9), [TechRepublic](https://www.techrepublic.com/article/why-python-is-so-popular-with-developers-3-reasons-the-language-has-exploded/), and [QZ](https://qz.com/1408660/the-rise-of-python-as-seen-through-a-decade-of-stack-overflow/)."
]
},
{
@ -771,14 +771,14 @@
}
},
"source": [
"**Part 1: Expressing Logic**\n",
"**Part A: Expressing Logic**\n",
"\n",
"- What is a programming language? What kind of words exist?\n",
" 1. [Elements of a Program](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb)\n",
" 2. [Functions & Modularization](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb)\n",
" - *Chapter 1*: [Elements of a Program](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_content.ipynb)\n",
" - *Chapter 2*: [Functions & Modularization](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_00_content.ipynb)\n",
"- What is the flow of execution? How can we form sentences from words?\n",
" 3. [Conditionals & Exceptions](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals.ipynb)\n",
" 4. [Recursion & Looping](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb)"
" - *Chapter 3*: [Conditionals & Exceptions](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_00_content.ipynb)\n",
" - *Chapter 4*: [Recursion & Looping](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb)"
]
},
{
@ -789,15 +789,16 @@
}
},
"source": [
"**Part 2: Managing Data and Memory**\n",
"**Part B: Managing Data and Memory**\n",
"\n",
"- How is data stored in memory?\n",
" 5. [Bits & Numbers](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers.ipynb)\n",
" 6. [Bytes & Text](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text.ipynb)\n",
" 7. [Sequential Data](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences.ipynb)\n",
" 8. [Mappings & Sets](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings.ipynb)\n",
" - *Chapter 5*: [Bits & Numbers](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers_00_content.ipynb)\n",
" - *Chapter 6*: [Bytes & Text](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text_00_content.ipynb)\n",
" - *Chapter 7*: [Sequential Data](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb)\n",
" - *Chapter 8*: [Mappings & Sets](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings_00_content.ipynb)\n",
" - *Chapter 9*: [Arrays & Dataframes](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/09_arrays_00_content.ipynb)\n",
"- How can we create custom data types?\n",
" 9. Object-Orientation"
" - *Chapter 10*: Object-Orientation"
]
},
{
@ -863,7 +864,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.7.4"
},
"livereveal": {
"auto_select": "code",
@ -891,5 +892,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View file

@ -11,14 +11,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Content Review"
"## Review"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 0](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/00_start_up.ipynb) of the book. Then work through the ten review questions."
"Read [Chapter 0](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/00_start_up_00_content.ipynb) of the book. Then, work through the questions below."
]
},
{
@ -32,14 +32,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions briefly with *at most* 300 characters per question!"
"Answer the following questions *briefly*!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1**: Describe the difference between the terms *programming* and *computer science*!"
"**Q1**: Describe the difference between the terms **programming** and **computer science**!"
]
},
{
@ -53,7 +53,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q2**: Explain what is a *pull request* and elaborate on how this concept fits a *distributed* organization of work!"
"**Q2**: Explain what is a **pull request** and elaborate on how this concept fits a *distributed* organization of work!"
]
},
{
@ -67,7 +67,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3**: In what sense are open-source communities democracies? How are they near-\"perfect\" [meritocracies](https://en.wikipedia.org/wiki/Meritocracy)? How is open-source software development similar to academia?"
"**Q3**: In what sense are **open-source** communities democracies? How are they near-perfect [meritocracies](https://en.wikipedia.org/wiki/Meritocracy)? How is open-source software development similar to academia?"
]
},
{
@ -81,7 +81,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q4**: What is a significant advantage of a \"slow\" programming language like Python over a faster one like C?"
"**Q4**: What is a *significant* advantage of a \"slow\" programming language like Python over a faster one like C?"
]
},
{
@ -182,69 +182,6 @@
"**Q10**: The primary purpose of PEPs is to regulate how code should be documented and styled."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## \"Coding\" Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Mastering Markdown"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Briefly review GitHub's guide on [Mastering Markdown](https://guides.github.com/features/mastering-markdown/) and create nicely formatted \"text\" cells below!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11**: Check the latest [Bundesliga standings](https://www.bundesliga.com/en/bundesliga/table) and provide a table of the top three teams with the following four columns: rank, team name, games played, and points scored. Render the rank in **bold**, make the team name a clickable link (to the team's website), and put both the games played and points scored in *italics*. The header row should be visually different from the three rows with the teams' information."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q12**: The quote \"Education is what remains after one has forgotten what one has learned in school\" is attributed to Albert Einstein. Display the author and his quote appropriately!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13**: Integrate this image (https://i.ytimg.com/vi/-BoSRlzy9c4/maxresdefault.jpg) of the delicious dessert **milk rice** into this notebook."
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -269,7 +206,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
@ -286,5 +223,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View file

@ -0,0 +1,115 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Chapter 0: Start up"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## \"Coding\" Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 0](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/00_start_up_00_content.ipynb) of the book. Then, work through the exercises below."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Mastering Markdown"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Briefly review GitHub's guide on [Mastering Markdown](https://guides.github.com/features/mastering-markdown/) and create nicely formatted \"text\" cells below!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1**: Check the latest [Bundesliga standings](https://www.bundesliga.com/en/bundesliga/table) and provide a table of the top three teams with the following four columns: rank, team name, games played, and points scored. Render the rank in **bold**, make the team name a clickable link (to the team's website), and put both the games played and points scored in *italics*. The header row should be visually different from the three rows with the teams' information."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q2**: The quote \"Education is what remains after one has forgotten what one has learned in school\" is attributed to Albert Einstein. Display the author and his quote appropriately!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3**: Integrate this image (https://i.ytimg.com/vi/-BoSRlzy9c4/maxresdefault.jpg) of the delicious dessert **milk rice** into this notebook."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}

File diff suppressed because one or more lines are too long

View file

@ -19,7 +19,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb) of the book. Then work through the ten review questions."
"Read [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_content.ipynb) of the book. Then, work through the questions below."
]
},
{
@ -33,7 +33,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions briefly with *at most* 300 characters per question!"
"Answer the following questions *briefly*!"
]
},
{
@ -152,7 +152,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q8**: The **Zen of Python** has a high opinion on Indian genius programmers."
"**Q8**: The **Zen of Python** talks about Indian genius programmers."
]
},
{
@ -189,92 +189,6 @@
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Coding Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Printing Output"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11.1**: Read about the [print()](https://docs.python.org/3/library/functions.html#print) built-in. How can you use it to print both `greeting` and `audience` *without* concatenating the two strings with the `+` operator?\n",
"\n",
"Hint: The `*objects` in the documentation implies that we can insert several comma-seperated variables."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"greeting = \"Hello\"\n",
"audience = \"World\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(...)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11.2**: What does the `sep=\" \"` mean in the documentation? Use it to print out the three names in `first`, `second`, and `third` on one line seperated by commas with one [print()](https://docs.python.org/3/library/functions.html#print) statement."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"first = \"Anthony\"\n",
"second = \"Berta\"\n",
"third = \"Christian\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(...)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11.3**: Lastly, what does the `end=\"\\n\"` mean in the documentation? Use it in the `for`-loop to print the numbers 1 through 10 in just one line."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for number in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:\n",
" print(...)"
]
}
],
"metadata": {
@ -293,7 +207,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
@ -310,5 +224,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View file

@ -0,0 +1,139 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Chapter 1: Elements of a Program"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Coding Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_content.ipynb) of the book. Then, work through the exercises below."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Printing Output"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.1**: Read about the [print()](https://docs.python.org/3/library/functions.html#print) built-in. How can you use it to print both `greeting` and `audience` *without* concatenating the two strings with the `+` operator?\n",
"\n",
"Hint: The `*objects` in the documentation implies that we can insert several comma-seperated variables."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"greeting = \"Hello\"\n",
"audience = \"World\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(...)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.2**: What does the `sep=\" \"` mean in the documentation? Use it to print out the three names in `first`, `second`, and `third` on one line seperated by commas with one [print()](https://docs.python.org/3/library/functions.html#print) statement."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"first = \"Anthony\"\n",
"second = \"Berta\"\n",
"third = \"Christian\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(...)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.3**: Lastly, what does the `end=\"\\n\"` mean in the documentation? Use it in the `for`-loop to print the numbers 1 through 10 in just one line."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for number in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:\n",
" print(...)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}

File diff suppressed because it is too large Load diff

View file

@ -18,7 +18,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb) of the book. Then work through the ten review questions."
"Read [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_00_content.ipynb) of the book. Then, work through the questions below."
]
},
{
@ -32,14 +32,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions briefly with *at most* 300 characters per question!"
"Answer the following questions *briefly*!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1**: What property of the `def` statement makes it a **statement**? Is there a way to use an **expression** to create a function?"
"**Q1**: What behavior of the `def` statement makes it a **statement**? Is there a way to use an **expression** to create a function?"
]
},
{
@ -182,188 +182,6 @@
"**Q10**: The [standard library](https://docs.python.org/3/library/index.html) is a collection of numerical tools often used in scientific computing, for example, advanced mathematical functions or utilities for simulation."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Coding Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Volume of a Sphere"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11.1**: The [volume of a sphere](https://en.wikipedia.org/wiki/Sphere) is defined as $\\frac{4}{3} * \\pi * r^3$. Calculate this value for $r=10.0$ and round it to 10 digits after the comma. Use the [standard library](https://docs.python.org/3/library/index.html) to obtain a good approximation of $\\pi$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"r = ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11.2**: Encapsulate the logic into a function `sphere_volume()` that takes one *positional* argument `radius` and one *keyword-only* argument `digits` defaulting to `5`. The volume should be returned as a `float` object under *all* circumstances. Document your work appropriately in a docstring according to [Google's Python Style Guide](https://github.com/google/styleguide/blob/gh-pages/pyguide.md)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def sphere_volume(...):\n",
" ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11.3**: Evaluate the function with `radius = 100.0` and 1, 5, 10, 15, and 20 digits respectively."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"radius = ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sphere_volume(...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sphere_volume(...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sphere_volume(...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sphere_volume(...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sphere_volume(...)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11.4**: What observation do you make?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11.5**: Using the [range()](https://docs.python.org/3/library/functions.html#func-range) built-in, write a `for`-loop and calculate the volume of a sphere with `radius = 42.0` for all `digits` from `1` through `20`. Print out each volume on a separate line.\n",
"\n",
"Note: This is the first task where you need to use the built-in [print()](https://docs.python.org/3/library/functions.html#print) function."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"radius = ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for ... in ...:\n",
" ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11.6**: What lesson do you learn about the `float` type?"
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -388,7 +206,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
@ -405,5 +223,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View file

@ -0,0 +1,234 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Chapter 2: Functions & Modularization"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Coding Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_00_content.ipynb) of the book. Then, work through the exercises below."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Volume of a Sphere"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.1**: The [volume of a sphere](https://en.wikipedia.org/wiki/Sphere) is defined as $\\frac{4}{3} * \\pi * r^3$. Calculate this value for $r=10.0$ and round it to 10 digits after the comma. Use the [standard library](https://docs.python.org/3/library/index.html) to obtain a good approximation of $\\pi$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"r = ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.2**: Encapsulate the logic into a function `sphere_volume()` that takes one *positional* argument `radius` and one *keyword-only* argument `digits` defaulting to `5`. The volume should be returned as a `float` object under *all* circumstances. Document your work appropriately in a docstring according to [Google's Python Style Guide](https://github.com/google/styleguide/blob/gh-pages/pyguide.md)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def sphere_volume(...):\n",
" ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.3**: Evaluate the function with `radius = 100.0` and 1, 5, 10, 15, and 20 digits respectively."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"radius = ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sphere_volume(...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sphere_volume(...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sphere_volume(...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sphere_volume(...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sphere_volume(...)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.4**: What observation do you make?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.5**: Using the [range()](https://docs.python.org/3/library/functions.html#func-range) built-in, write a `for`-loop and calculate the volume of a sphere with `radius = 42.0` for all `digits` from `1` through `20`. Print out each volume on a separate line.\n",
"\n",
"Note: This is the first task where you need to use the built-in [print()](https://docs.python.org/3/library/functions.html#print) function."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"radius = ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for ... in ...:\n",
" ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.6**: What lesson do you learn about the `float` type?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View file

@ -19,7 +19,7 @@
}
},
"source": [
"We analyzed every aspect of the `average_evens()` function in [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb) except for the `if`-related parts. While it seems to do what we expect it to, there is a whole lot more we learn from taking it apart. In particular, the `if` may occur within both a **statement** or an **expression**, analogous as to how a noun in a natural language is *either* the subject of *or* an object in a sentence. What is common to both usages is that it leads to code being executed for *parts* of the input only. It is our first way of **controlling** the **flow of execution** in a program.\n",
"We analyzed every aspect of the `average_evens()` function in [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_00_content.ipynb) except for the `if`-related parts. While it seems to do what we expect it to, there is a whole lot more we learn from taking it apart. In particular, the `if` may occur within both a **statement** or an **expression**, analogous as to how a noun in a natural language is *either* the subject of *or* an object in a sentence. What is common to both usages is that it leads to code being executed for *parts* of the input only. It is our first way of **controlling** the **flow of execution** in a program.\n",
"\n",
"After deconstructing `if` in the first part of this chapter, we take a close look at a similar concept, namely handling **exceptions**."
]
@ -139,7 +139,7 @@
}
},
"source": [
"There are, however, cases where even well-behaved Python does not make us happy. [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers.ipynb#Imprecision) provides more insights into this \"bug.\""
"There are, however, cases where even well-behaved Python does not make us happy. [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers_00_content.ipynb#Imprecision) provides more insights into this \"bug.\""
]
},
{
@ -189,7 +189,7 @@
{
"data": {
"text/plain": [
"93918328484832"
"94426021241472"
]
},
"execution_count": 5,
@ -213,7 +213,7 @@
{
"data": {
"text/plain": [
"93918328484800"
"94426021241440"
]
},
"execution_count": 6,
@ -281,7 +281,7 @@
}
},
"source": [
"Let's not confuse the boolean `False` with `None`, another built-in object! We saw the latter before in [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb#Function-Definition) as the *implicit* return value of a function without a `return` statement.\n",
"Let's not confuse the boolean `False` with `None`, another built-in object! We saw the latter before in [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_00_content.ipynb#Function-Definition) as the *implicit* return value of a function without a `return` statement.\n",
"\n",
"We might think of `None` in a boolean context indicating a \"maybe\" or even an \"unknown\" answer; however, for Python, there are no \"maybe\" or \"unknown\" objects, as we see further below!\n",
"\n",
@ -313,7 +313,7 @@
{
"data": {
"text/plain": [
"93918328471792"
"94426021228432"
]
},
"execution_count": 10,
@ -357,7 +357,7 @@
}
},
"source": [
"`True`, `False`, and `None` have the property that they each exist in memory only *once*. Objects designed this way are so-called **singletons**. This **[design pattern](https://en.wikipedia.org/wiki/Design_Patterns)** was originally developed to keep a program's memory usage at a minimum. It may only be employed in situations where we know that an object does *not* mutate its value (i.e., to reuse the bag analogy from [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb#Objects-vs.-Types-vs.-Values), no flipping of $0$s and $1$s in the bag is allowed). In languages \"closer\" to the memory like C, we would have to code this singleton logic ourselves, but Python has this built in for *some* types.\n",
"`True`, `False`, and `None` have the property that they each exist in memory only *once*. Objects designed this way are so-called **singletons**. This **[design pattern](https://en.wikipedia.org/wiki/Design_Patterns)** was originally developed to keep a program's memory usage at a minimum. It may only be employed in situations where we know that an object does *not* mutate its value (i.e., to reuse the bag analogy from [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_content.ipynb#Objects-vs.-Types-vs.-Values), no flipping of $0$s and $1$s in the bag is allowed). In languages \"closer\" to the memory like C, we would have to code this singleton logic ourselves, but Python has this built in for *some* types.\n",
"\n",
"We verify this with either the `is` operator or by comparing memory addresses."
]
@ -1116,6 +1116,65 @@
"bool([False])"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"With `str` objects, the empty `\"\"` evaluates to `False`, and any other to `True`."
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bool(\"\")"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bool(\"Lorem ipsum dolor sit amet, ...\")"
]
},
{
"cell_type": "markdown",
"metadata": {
@ -1162,7 +1221,7 @@
},
{
"cell_type": "code",
"execution_count": 36,
"execution_count": 38,
"metadata": {
"slideshow": {
"slide_type": "slide"
@ -1187,75 +1246,12 @@
"With the `or` operator, the first truthy sub-expression is returned."
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Arg: 0\n",
"Arg: 1\n"
]
},
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"expr(0) or expr(1)"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Arg: 1\n"
]
},
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"expr(1) or expr(2) # 2 is not evaluated due to short-circuiting"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"slideshow": {
"slide_type": "-"
"slide_type": "slide"
}
},
"outputs": [
@ -1278,6 +1274,69 @@
"output_type": "execute_result"
}
],
"source": [
"expr(0) or expr(1)"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Arg: 1\n"
]
},
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"expr(1) or expr(2) # 2 is not evaluated due to short-circuiting"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Arg: 0\n",
"Arg: 1\n"
]
},
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"expr(0) or expr(1) or expr(2) # 2 is not evaluated due to short-circuiting"
]
@ -1295,7 +1354,7 @@
},
{
"cell_type": "code",
"execution_count": 40,
"execution_count": 42,
"metadata": {
"slideshow": {
"slide_type": "fragment"
@ -1317,7 +1376,7 @@
"0"
]
},
"execution_count": 40,
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
@ -1339,7 +1398,7 @@
},
{
"cell_type": "code",
"execution_count": 41,
"execution_count": 43,
"metadata": {
"slideshow": {
"slide_type": "slide"
@ -1359,7 +1418,7 @@
"0"
]
},
"execution_count": 41,
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
@ -1370,7 +1429,7 @@
},
{
"cell_type": "code",
"execution_count": 42,
"execution_count": 44,
"metadata": {
"slideshow": {
"slide_type": "-"
@ -1391,7 +1450,7 @@
"0"
]
},
"execution_count": 42,
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
@ -1402,7 +1461,7 @@
},
{
"cell_type": "code",
"execution_count": 43,
"execution_count": 45,
"metadata": {
"slideshow": {
"slide_type": "-"
@ -1423,7 +1482,7 @@
"0"
]
},
"execution_count": 43,
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
@ -1445,7 +1504,7 @@
},
{
"cell_type": "code",
"execution_count": 44,
"execution_count": 46,
"metadata": {
"slideshow": {
"slide_type": "fragment"
@ -1466,7 +1525,7 @@
"2"
]
},
"execution_count": 44,
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
@ -1522,7 +1581,7 @@
},
{
"cell_type": "code",
"execution_count": 45,
"execution_count": 47,
"metadata": {
"code_folding": [],
"slideshow": {
@ -1536,7 +1595,7 @@
},
{
"cell_type": "code",
"execution_count": 46,
"execution_count": 48,
"metadata": {
"code_folding": [],
"slideshow": {
@ -1578,7 +1637,7 @@
},
{
"cell_type": "code",
"execution_count": 47,
"execution_count": 49,
"metadata": {
"slideshow": {
"slide_type": "slide"
@ -1591,7 +1650,7 @@
},
{
"cell_type": "code",
"execution_count": 48,
"execution_count": 50,
"metadata": {
"slideshow": {
"slide_type": "-"
@ -1616,7 +1675,7 @@
},
{
"cell_type": "code",
"execution_count": 49,
"execution_count": 51,
"metadata": {
"slideshow": {
"slide_type": "skip"
@ -1653,7 +1712,7 @@
},
{
"cell_type": "code",
"execution_count": 50,
"execution_count": 52,
"metadata": {
"slideshow": {
"slide_type": "slide"
@ -1696,7 +1755,7 @@
},
{
"cell_type": "code",
"execution_count": 51,
"execution_count": 53,
"metadata": {
"slideshow": {
"slide_type": "slide"
@ -1769,7 +1828,7 @@
},
{
"cell_type": "code",
"execution_count": 52,
"execution_count": 54,
"metadata": {
"slideshow": {
"slide_type": "slide"
@ -1793,7 +1852,7 @@
},
{
"cell_type": "code",
"execution_count": 53,
"execution_count": 55,
"metadata": {
"slideshow": {
"slide_type": "-"
@ -1807,60 +1866,12 @@
" y = x ** 2"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"data": {
"text/plain": [
"9"
]
},
"execution_count": 54,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"y"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"On the contrary, the `if` expression fits into one line. The main downside is a potential loss in readability, in particular, if the functional relationship is not that simple. Also, some practitioners do *not* like that the condition is in the middle of the expression."
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"y = 0 if x <= 0 else x ** 2"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {
"slideshow": {
"slide_type": "skip"
"slide_type": "-"
}
},
"outputs": [
@ -1887,7 +1898,7 @@
}
},
"source": [
"In this example, however, the most elegant solution is to use the built-in [max()](https://docs.python.org/3/library/functions.html#max) function."
"On the contrary, the `if` expression fits into one line. The main downside is a potential loss in readability, in particular, if the functional relationship is not that simple. Also, some practitioners do *not* like that the condition is in the middle of the expression."
]
},
{
@ -1900,7 +1911,7 @@
},
"outputs": [],
"source": [
"y = max(0, x) ** 2"
"y = 0 if x <= 0 else x ** 2"
]
},
{
@ -1927,6 +1938,54 @@
"y"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"In this example, however, the most elegant solution is to use the built-in [max()](https://docs.python.org/3/library/functions.html#max) function."
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"y = max(0, x) ** 2"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [
{
"data": {
"text/plain": [
"9"
]
},
"execution_count": 60,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"y"
]
},
{
"cell_type": "markdown",
"metadata": {
@ -1955,7 +2014,7 @@
},
{
"cell_type": "code",
"execution_count": 59,
"execution_count": 61,
"metadata": {
"slideshow": {
"slide_type": "slide"
@ -1968,7 +2027,7 @@
},
{
"cell_type": "code",
"execution_count": 60,
"execution_count": 62,
"metadata": {
"slideshow": {
"slide_type": "-"
@ -2007,7 +2066,7 @@
},
{
"cell_type": "code",
"execution_count": 61,
"execution_count": 63,
"metadata": {
"slideshow": {
"slide_type": "fragment"
@ -2046,7 +2105,7 @@
},
{
"cell_type": "code",
"execution_count": 62,
"execution_count": 64,
"metadata": {
"slideshow": {
"slide_type": "slide"
@ -2057,7 +2116,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Oops. Division by 0. How does that work?\n",
"Yes, division worked smoothly.\n",
"I am always printed\n"
]
}
@ -2119,7 +2178,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.7.4"
},
"livereveal": {
"auto_select": "code",
@ -2147,5 +2206,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View file

@ -0,0 +1,214 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Chapter 3: Conditionals & Exceptions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Content Review"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 3](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_00_content.ipynb) of the book. Then, work through the questions below."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Essay Questions "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions *briefly*!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1**: What is the **singleton** design pattern? How many objects does the expression `[True, False, True, False]` generate in memory?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q2**: What do we mean when we talk about **truthy** and **falsy** expressions?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3**: Describe in your own words the concept of **short-circuiting**! What does it imply for an individual sub-expression in a boolean expression?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q4**: Explain how the conceptual difference between a **statement** and an **expression** relates to the difference between a **conditional statement** and a **conditional expression**."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q5**: Why is the use of **temporary variables** encouraged in Python?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q6**: What does the `finally`-clause enforce in this code snippet? How can a `try` statement be useful *without* an `except`-clause?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```python\n",
"try:\n",
" print(\"Make a request to a service on the internet\")\n",
"finally:\n",
" print(\"This could be clean-up code\")\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### True / False Questions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Motivate your answer with *one short* sentence!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7**: The objects `True`, `False`, and `None` represent the idea of *yes*, *no*, and *maybe* answers in a natural language.\n",
"\n",
"Hint: you also respond with a code cell."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q8**: The `try` statement is useful for handling **syntax** errors."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View file

@ -8,174 +8,6 @@
"# Chapter 3: Conditionals & Exceptions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Content Review"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 3](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals.ipynb) of the book. Then work through the eight review questions."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Essay Questions "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions briefly with *at most* 300 characters per question!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1**: What is the **singleton** design pattern? How many objects does the expression `[True, False, True, False]` generate in memory?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q2**: What do we mean when we talk about **truthy** and **falsy** expressions?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3**: Describe in your own words the concept of **short-circuiting**! What does it imply for an individual sub-expression in a boolean expression?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q4**: Explain how the conceptual difference between a **statement** and an **expression** relates to the difference between a **conditional statement** and a **conditional expression**."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q5**: Why is the use of **temporary variables** encouraged in Python?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q6**: What does the `finally`-clause enforce in this code snippet? How can a `try` statement be useful *without* an `except`-clause?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```python\n",
"try:\n",
" print(\"Make a request to a service on the internet\")\n",
"finally:\n",
" print(\"This could be clean-up code\")\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### True / False Questions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Motivate your answer with *one short* sentence!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7**: The objects `True`, `False`, and `None` represent the idea of *yes*, *no*, and *maybe* answers in a natural language.\n",
"\n",
"Hint: you also respond with a code cell."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q8**: The `try` statement is useful for handling **syntax** errors."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -183,6 +15,13 @@
"## Coding Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 3](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_00_content.ipynb) of the book. Then, work through the exercises below."
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -194,7 +33,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9.1**: Write a function `discounted_price()` that takes the positional arguments `unit_price` (of type `float`) and `quantity` (of type `int`) and implements a discount scheme for a line item in a customer order as follows:\n",
"**Q1.1**: Write a function `discounted_price()` that takes the positional arguments `unit_price` (of type `float`) and `quantity` (of type `int`) and implements a discount scheme for a line item in a customer order as follows:\n",
"\n",
"- if the unit price is over 100 dollars, grant 10% relative discount\n",
"- if a customer orders more than 10 items, one in every five items is for free\n",
@ -218,7 +57,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9.2**: Calculate the final price for the following line items of an order:\n",
"**Q1.2**: Calculate the final price for the following line items of an order:\n",
"- $7$ smartphones @ $99.00$ USD\n",
"- $3$ workstations @ $999.00$ USD\n",
"- $19$ GPUs @ $879.95$ USD\n",
@ -265,7 +104,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9.3**: Calculate the last two line items with order quantities of $20$ and $15$. What do you observe?"
"**Q1.3**: Calculate the last two line items with order quantities of $20$ and $15$. What do you observe?"
]
},
{
@ -297,7 +136,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9.4**: Looking at the `if`-`else`-logic in the function, why do you think the four example line items in **Q9.2** were chosen as they were?"
"**Q1.4**: Looking at the `if`-`else`-logic in the function, why do you think the four example line items in **Q9.2** were chosen as they were?"
]
},
{
@ -327,7 +166,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q10.1**: First, create a list `numbers` with the numbers from 1 through 100. You could type all numbers manually, but there is, of course, a smarter way. The built-in [range()](https://docs.python.org/3/library/functions.html#func-range) may be useful here. Read how it works in the documentation. To make the output of [range()](https://docs.python.org/3/library/functions.html#func-range) a `list` object, you have to wrap it with the [list()](https://docs.python.org/3/library/functions.html#func-list) built-in (i.e., `list(range(...))`)."
"**Q2.1**: First, create a list `numbers` with the numbers from 1 through 100. You could type all numbers manually, but there is, of course, a smarter way. The built-in [range()](https://docs.python.org/3/library/functions.html#func-range) may be useful here. Read how it works in the documentation. To make the output of [range()](https://docs.python.org/3/library/functions.html#func-range) a `list` object, you have to wrap it with the [list()](https://docs.python.org/3/library/functions.html#func-list) built-in (i.e., `list(range(...))`)."
]
},
{
@ -343,9 +182,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q10.2**: Loop over the `numbers` list and replace numbers for which one of the two (or both) conditions apply with text strings `\"Fizz\"`, `\"Buzz\"`, or `\"FizzBuzz\"` using the indexing operator `[]` and the assignment statement `=`.\n",
"**Q2.2**: Loop over the `numbers` list and replace numbers for which one of the two (or both) conditions apply with text strings `\"Fizz\"`, `\"Buzz\"`, or `\"FizzBuzz\"` using the indexing operator `[]` and the assignment statement `=`.\n",
"\n",
"In [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb), we saw that Python starts indexing with `0` as the first element. Keep that in mind.\n",
"In [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_content.ipynb), we saw that Python starts indexing with `0` as the first element. Keep that in mind.\n",
"\n",
"So in each iteration of the `for`-loop, you have to determine an `index` variable as well as check the actual `number` for its divisors.\n",
"\n",
@ -366,7 +205,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q10.3**: Create a loop that prints out either the number or any of the Fizz Buzz substitutes. Do it in such a way that we do not end up with 100 lines of output here."
"**Q2.3**: Create a loop that prints out either the number or any of the Fizz Buzz substitutes. Do it in such a way that we do not end up with 100 lines of output here."
]
},
{
@ -396,7 +235,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
@ -413,5 +252,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View file

@ -839,9 +839,9 @@
"source": [
"This implementation is *highly* **inefficient** as small Fibonacci numbers already take a very long time to compute. The reason for this is **exponential growth** in the number of function calls. As [PythonTutor](http://pythontutor.com/visualize.html#code=def%20fibonacci%28i%29%3A%0A%20%20%20%20if%20i%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20return%200%0A%20%20%20%20elif%20i%20%3D%3D%201%3A%0A%20%20%20%20%20%20%20%20return%201%0A%20%20%20%20return%20fibonacci%28i%20-%201%29%20%2B%20fibonacci%28i%20-%202%29%0A%0Arv%20%3D%20fibonacci%285%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) shows, `fibonacci()` is called again and again with the same `i` arguments.\n",
"\n",
"To understand this in detail, we would have to study algorithms and data structures (e.g., with [this book](https://www.amazon.de/Introduction-Algorithms-Press-Thomas-Cormen/dp/0262033844/ref=sr_1_1?__mk_de_DE=%C3%85M%C3%85%C5%BD%C3%95%C3%91&crid=1JNE8U0VZGU0O&qid=1569837169&s=gateway&sprefix=algorithms+an%2Caps%2C180&sr=8-1)), a discipline within computer science, and dive into the analysis of **[time complexity of algorithms](https://en.wikipedia.org/wiki/Time_complexity)**.\n",
"To understand this in detail, we have to study algorithms and data structures (e.g., with [this book](https://www.amazon.de/Introduction-Algorithms-Press-Thomas-Cormen/dp/0262033844/ref=sr_1_1?__mk_de_DE=%C3%85M%C3%85%C5%BD%C3%95%C3%91&crid=1JNE8U0VZGU0O&qid=1569837169&s=gateway&sprefix=algorithms+an%2Caps%2C180&sr=8-1)), a discipline within computer science, and dive into the analysis of **[time complexity of algorithms](https://en.wikipedia.org/wiki/Time_complexity)**.\n",
"\n",
"Luckily, in the Fibonacci case, the inefficiency can be resolved with a **caching** (i.e., \"reuse\") strategy from the field of **[dynamic programming](https://en.wikipedia.org/wiki/Dynamic_programming)**, namely **[memoization](https://en.wikipedia.org/wiki/Memoization)**. We do so in [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings.ipynb#Memoization), after introducing the [dictionaries](https://docs.python.org/3/library/stdtypes.html#dict) data type.\n",
"Luckily, in the Fibonacci case, the inefficiency can be resolved with a **caching** (i.e., \"reuse\") strategy from the field of **[dynamic programming](https://en.wikipedia.org/wiki/Dynamic_programming)**, namely **[memoization](https://en.wikipedia.org/wiki/Memoization)**. We do so in [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings_00_content.ipynb#Memoization), after introducing the `dict` data type.\n",
"\n",
"Let's measure the average run times for `fibonacci()` and varying `i` arguments with the `%%timeit` [cell magic](https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-timeit) that comes with Jupyter."
]
@ -859,7 +859,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"37.5 µs ± 4.26 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
"49.8 µs ± 20.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
]
}
],
@ -881,7 +881,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"1.49 ms ± 22.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
"1.63 ms ± 14.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
]
}
],
@ -903,7 +903,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"199 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
"202 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
]
}
],
@ -925,7 +925,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"2.04 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
"2.25 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
]
}
],
@ -947,7 +947,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"5.33 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
"5.79 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
]
}
],
@ -4538,7 +4538,7 @@
}
},
"source": [
"##### Efficiency of Algorithms (revisited)"
"##### Efficiency of Algorithms (continued)"
]
},
{
@ -4565,7 +4565,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"4.6 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
"5.14 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
]
}
],
@ -4877,7 +4877,7 @@
}
},
"source": [
"For sequences of integers, the [range()](https://docs.python.org/3/library/functions.html#func-range) built-in makes the `for` statement even more convenient: It creates a `list`-like object of type `range` that generates integers \"on the fly,\" and we look closely at the underlying effects in memory in [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences.ipynb#Mapping)."
"For sequences of integers, the [range()](https://docs.python.org/3/library/functions.html#func-range) built-in makes the `for` statement even more convenient: It creates a `list`-like object of type `range` that generates integers \"on the fly,\" and we look closely at the underlying effects in memory in [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb#Mapping)."
]
},
{
@ -5008,11 +5008,11 @@
"\n",
"Now, just as we classify objects by data type, we also classify these data types (e.g., `int`, `float`, `str`, or `list`) into **abstract concepts**.\n",
"\n",
"We did this already in [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb#Who-am-I?-And-how-many?) when we described a `list` object as \"some sort of container that holds [...] references to other objects\". So, abstractly speaking, **containers** are any objects that are \"composed\" of other objects and also \"manage\" how these objects are organized. `list` objects, for example, have the property that they model an order associated with their elements. There exist, however, other container types, many of which do *not* come with an order. So, containers primarily \"contain\" other objects and have *nothing* to do with looping.\n",
"We did this already in [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_content.ipynb#Who-am-I?-And-how-many?) when we described a `list` object as \"some sort of container that holds [...] references to other objects\". So, abstractly speaking, **containers** are any objects that are \"composed\" of other objects and also \"manage\" how these objects are organized. `list` objects, for example, have the property that they model an order associated with their elements. There exist, however, other container types, many of which do *not* come with an order. So, containers primarily \"contain\" other objects and have *nothing* to do with looping.\n",
"\n",
"On the contrary, the abstract concept of **iterables** is all about looping: Any object that we can loop over is, by definition, an iterable. So, `range` objects, for example, are iterables, even though they hold no references to other objects. Moreover, looping does *not* have to occur in a *predictable* order, although this is the case for both `list` and `range` objects.\n",
"\n",
"Typically, containers are iterables, and iterables are containers. Yet, only because these two concepts coincide often, we must not think of them as the same. In [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences.ipynb#Collections-vs.-Sequences), we formalize these two concepts and introduce many more. Finally, Chapter 9 gives an explanation how abstract concepts are implemented and play together.\n",
"Typically, containers are iterables, and iterables are containers. Yet, only because these two concepts coincide often, we must not think of them as the same. In [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb#Collections-vs.-Sequences), we formalize these two concepts and introduce many more. Finally, Chapter 10 gives an explanation how abstract concepts are implemented and play together.\n",
"\n",
"Let's continue with `first_names` below as an example an illustrate what iterable containers are."
]
@ -5399,7 +5399,7 @@
}
},
"source": [
"##### Efficiency of Algorithms (revisited)"
"##### Efficiency of Algorithms (continued)"
]
},
{
@ -5574,7 +5574,7 @@
}
},
"source": [
"Let's say we have a `samples` list and want to check if the square of at least one of its elements is above a `threshold` of `100`."
"Let's say we have a list of `numbers` and want to check if the square of at least one of its elements is above a `threshold` of `100`."
]
},
{
@ -5587,7 +5587,7 @@
},
"outputs": [],
"source": [
"samples = [3, 7, 2, 9, 11, 4, 7, 9, 4, 5]"
"numbers = [7, 11, 8, 5, 3, 12, 2, 6, 9, 10, 1, 4]"
]
},
{
@ -5611,7 +5611,7 @@
}
},
"source": [
"A first naive implementation could look like this: We loop over *every* element in `samples` and set an **indicator variable** `is_above`, initialized as `False`, to `True` once we encounter an element satisfying the search condition."
"A first naive implementation could look like this: We loop over *every* element in `numbers` and set an **indicator variable** `is_above`, initialized as `False`, to `True` once we encounter an element satisfying the search condition."
]
},
{
@ -5627,22 +5627,22 @@
"name": "stdout",
"output_type": "stream",
"text": [
"3 7 2 9 11 4 7 9 4 5 => at least one sample's square is above 100\n"
"7 11 8 5 3 12 2 6 9 10 1 4 => at least one number's square is above 100\n"
]
}
],
"source": [
"is_above = False\n",
"\n",
"for sample in samples:\n",
" print(sample, end=\" \") # added for didactical purposes\n",
" if sample ** 2 > threshold:\n",
"for number in numbers:\n",
" print(number, end=\" \") # added for didactical purposes\n",
" if number ** 2 > threshold:\n",
" is_above = True\n",
"\n",
"if is_above:\n",
" print(\"=> at least one sample's square is above\", threshold)\n",
" print(\"=> at least one number's square is above\", threshold)\n",
"else:\n",
" print(\"=> no sample's square is above\", threshold)"
" print(\"=> no number's square is above\", threshold)"
]
},
{
@ -5653,7 +5653,7 @@
}
},
"source": [
"This implementation is *inefficient* as even if the *first* element in `samples` has a square greater than `100`, we loop until the last element: This could take a long time for a big list.\n",
"This implementation is *inefficient* as even if the *first* element in `numbers` has a square greater than `100`, we loop until the last element: This could take a long time for a big list.\n",
"\n",
"Moreover, we must initialize `is_above` *before* the `for`-loop and write an `if`-`else`-logic *after* it to check for the result. The actual business logic is *not* clear right away.\n",
"\n",
@ -5673,23 +5673,23 @@
"name": "stdout",
"output_type": "stream",
"text": [
"3 7 2 9 11 => at least one sample's square is above 100\n"
"7 11 => at least one number's square is above 100\n"
]
}
],
"source": [
"is_above = False\n",
"\n",
"for sample in samples:\n",
" print(sample, end=\" \") # added for didactical purposes\n",
" if sample ** 2 > threshold:\n",
"for number in numbers:\n",
" print(number, end=\" \") # added for didactical purposes\n",
" if number ** 2 > threshold:\n",
" is_above = True\n",
" break\n",
"\n",
"if is_above:\n",
" print(\"=> at least one sample's square is above\", threshold)\n",
" print(\"=> at least one number's square is above\", threshold)\n",
"else:\n",
" print(\"=> no sample's square is above\", threshold)"
" print(\"=> no number's square is above\", threshold)"
]
},
{
@ -5751,23 +5751,23 @@
"name": "stdout",
"output_type": "stream",
"text": [
"3 7 2 9 11 => at least one sample's square is above 100\n"
"7 11 => at least one number's square is above 100\n"
]
}
],
"source": [
"for sample in samples:\n",
" print(sample, end=\" \") # added for didactical purposes\n",
" if sample ** 2 > threshold:\n",
"for number in numbers:\n",
" print(number, end=\" \") # added for didactical purposes\n",
" if number ** 2 > threshold:\n",
" is_above = True\n",
" break\n",
"else:\n",
" is_above = False\n",
"\n",
"if is_above:\n",
" print(\"=> at least one sample's square is above\", threshold)\n",
" print(\"=> at least one number's square is above\", threshold)\n",
"else:\n",
" print(\"=> no sample's square is above\", threshold)"
" print(\"=> no number's square is above\", threshold)"
]
},
{
@ -5794,18 +5794,18 @@
"name": "stdout",
"output_type": "stream",
"text": [
"3 7 2 9 11 => at least one sample's square is above 100\n"
"7 11 => at least one number's square is above 100\n"
]
}
],
"source": [
"for sample in samples:\n",
" print(sample, end=\" \") # added for didactical purposes\n",
" if sample ** 2 > threshold:\n",
" print(\"=> at least one sample's square is above\", threshold)\n",
"for number in numbers:\n",
" print(number, end=\" \") # added for didactical purposes\n",
" if number ** 2 > threshold:\n",
" print(\"=> at least one number's square is above\", threshold)\n",
" break\n",
"else:\n",
" print(\"=> no sample's square is above\", threshold)"
" print(\"=> no number's square is above\", threshold)"
]
},
{
@ -5816,7 +5816,7 @@
}
},
"source": [
"Of course, if we set the `threshold` an element's square has to pass higher, for example, to `200`, we have to loop over all `samples`. There is *no way* to optimize this **[linear search](https://en.wikipedia.org/wiki/Linear_search)** further, at least as long as we model `samples` as a `list` object. More advanced data types, however, exist that mitigate that downside."
"Of course, if we set the `threshold` an element's square has to pass higher, for example, to `200`, we have to loop over all `numbers`. There is *no way* to optimize this **[linear search](https://en.wikipedia.org/wiki/Linear_search)** further, at least as long as we model `numbers` as a `list` object. More advanced data types, however, exist that mitigate that downside."
]
},
{
@ -5832,20 +5832,20 @@
"name": "stdout",
"output_type": "stream",
"text": [
"3 7 2 9 11 4 7 9 4 5 => no sample's square is above 200\n"
"7 11 8 5 3 12 2 6 9 10 1 4 => no number's square is above 200\n"
]
}
],
"source": [
"threshold = 200\n",
"\n",
"for sample in samples:\n",
" print(sample, end=\" \") # added for didactical purposes\n",
" if sample ** 2 > threshold:\n",
" print(\"=> at least one sample's square is above\", threshold)\n",
"for number in numbers:\n",
" print(number, end=\" \") # added for didactical purposes\n",
" if number ** 2 > threshold:\n",
" print(\"=> at least one number's square is above\", threshold)\n",
" break\n",
"else:\n",
" print(\"=> no sample's square is above\", threshold)"
" print(\"=> no number's square is above\", threshold)"
]
},
{
@ -5867,17 +5867,17 @@
}
},
"source": [
"Often, we process some iterable with numeric data, for example, a list of `numbers` as in this book's introductory example in [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb#Example:-Averaging-Even-Numbers) or, more realistically, data from a CSV file with many rows and columns.\n",
"Often, we process some iterable with numeric data, for example, a list of `numbers` as in this book's introductory example in [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_content.ipynb#Example:-Averaging-Even-Numbers) or, more realistically, data from a CSV file with many rows and columns.\n",
"\n",
"Processing numeric data usually comes down to operations that may be grouped into one of the following three categories:\n",
"\n",
"- **mapping**: transform a sample according to some functional relationship $y = f(x)$\n",
"- **filtering**: throw away individual samples (e.g., statistical outliers)\n",
"- **reducing**: collect individual samples into summary statistics\n",
"- **mapping**: transform a number according to some functional relationship $y = f(x)$\n",
"- **filtering**: throw away individual numbers (e.g., statistical outliers in a sample)\n",
"- **reducing**: collect individual numbers into summary statistics\n",
"\n",
"We study this **map-filter-reduce** paradigm extensively in [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences.ipynb#The-Map-Filter-Reduce-Paradigm) after introducing more advanced data types that are needed to work with \"big\" data.\n",
"We study this **map-filter-reduce** paradigm extensively in [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb#The-Map-Filter-Reduce-Paradigm) after introducing more advanced data types that are needed to work with \"big\" data.\n",
"\n",
"In the remainder of this section, we focus on *filtering out* some samples within a `for`-loop."
"Here, we focus on *filtering out* some numbers with a `for`-loop."
]
},
{
@ -6074,7 +6074,7 @@
}
},
"source": [
"With already three levels of indentation, less horizontal space is available for the actual code block. Of course, one could flatten the two `if` statements with the logical `and` operator, as shown in [Chapter 3](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals.ipynb#The-if-Statement). Then, however, we trade off horizontal space against a more \"complex\" `if` logic, and this is *not* a real improvement.\n",
"With already three levels of indentation, less horizontal space is available for the actual code block. Of course, one could flatten the two `if` statements with the logical `and` operator, as shown in [Chapter 3](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_00_content.ipynb#The-if-Statement). Then, however, we trade off horizontal space against a more \"complex\" `if` logic, and this is *not* a real improvement.\n",
"\n",
"A Pythonista would instead make use of the `continue` statement (cf., [reference](https://docs.python.org/3/reference/simple_stmts.html#the-continue-statement)) that causes a loop to jump into the next iteration skipping the rest of the code block.\n",
"\n",
@ -6236,13 +6236,31 @@
}
},
"outputs": [
{
"name": "stdin",
"output_type": "stream",
"text": [
"Guess if the coin comes up as heads or tails: Tails\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Ooops, it was tails\n"
]
},
{
"name": "stdin",
"output_type": "stream",
"text": [
"Guess if the coin comes up as heads or tails: heads\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Guess if the coin comes up as heads or tails: Tails\n",
"Ooops, it was tails\n",
"Guess if the coin comes up as heads or tails: heads\n",
"Yes, it was heads\n"
]
}
@ -6402,13 +6420,31 @@
}
},
"outputs": [
{
"name": "stdin",
"output_type": "stream",
"text": [
"Guess if the coin comes up as heads or tails: invalid\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Make sure to enter your guess correctly!\n"
]
},
{
"name": "stdin",
"output_type": "stream",
"text": [
"Guess if the coin comes up as heads or tails: Heads\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Guess if the coin comes up as heads or tails: invalid\n",
"Make sure to enter your guess correctly!\n",
"Guess if the coin comes up as heads or tails: Heads\n",
"Yes, it was heads\n"
]
}
@ -6485,7 +6521,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.7.4"
},
"livereveal": {
"auto_select": "code",
@ -6513,5 +6549,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View file

@ -0,0 +1,281 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Chapter 4: Recursion & Looping"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Content Review"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb) of the book. Then, work through the questions below."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Essay Questions "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions *briefly*!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1**: Solving a problem by **recursion** is not only popular in computer science and math. Name some examples from the fields of business or economics where problems are also solved in a **backward** fashion!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q2**: Explain what **duck typing** means! Why can it cause problems? Why is it [not a bug but a feature](https://www.urbandictionary.com/define.php?term=It%27s%20not%20a%20bug%2C%20it%27s%20a%20feature)?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3**: What is **syntactic sugar**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q4**: Describe in your own words why the **recursive** version of `fibonacci()`, the \"Easy at first Glance\" example in the chapter, is computationally **inefficient**! Why does the **iterative** version of `fibonacci()`, the \"Hard at first Glance\" example, run so much faster?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q5**: What is the conceptual difference between a **container** and a **list**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q6**: What is a good use case for the `for`-loop's optional `else`-clause?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### True / False Questions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Motivate your answer with *one short* sentence!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7**: When a **recursion** does **not** reach the base case, this is an example of the **early exit** strategy."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q8**: Any programming language **without** looping constructs like the `for` or `while` statements is **not** Turing complete."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9**: A **recursive** formulation is the same as a **circular** one: The terms are **synonyms**."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q10**: Formulating a computational problem as a **recursion** results in an **efficient** implementation."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11**: Whereas a **recursion** may accidentally result in a **never-ending** program, `while`-loops and `for`-loops are guaranteed to **terminate**."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q12**: Before writing **any** kind of **loop**, we **always** need to think about a **stopping criterion** ahead of time."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13**: **Container** types such as `list` objects are characterized by their **support** for **being looped over**, for example as in:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```python\n",
"for element in container:\n",
" # do something for every element\n",
" ...\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View file

@ -8,255 +8,6 @@
"# Chapter 4: Recursion & Looping"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Content Review"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb) of the book. Then work through the fourteen review questions."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Essay Questions "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions briefly with *at most* 300 characters per question!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1**: What is so \"special\" about the number **7919**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q2**: Solving a problem by **recursion** is not only popular in computer science and math. Name some examples from the fields of business or economics where problems are also solved in a **backward** fashion!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3**: Explain what **duck typing** means! Why can it cause problems? Why is it [not a bug but a feature](https://www.urbandictionary.com/define.php?term=It%27s%20not%20a%20bug%2C%20it%27s%20a%20feature)?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q4**: What is **syntactic sugar**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q5**: Describe in your own words why the **recursive** version of `fibonacci()`, the \"Easy at first Glance\" example in the chapter, is computationally **inefficient**! Why does the **iterative** version of `fibonacci()`, the \"Hard at first Glance\" example, run so much faster?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q6**: What is the conceptual difference between a **container** and a **list**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7**: What is a good use case for the `for`-loop's optional `else`-clause?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### True / False Questions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Motivate your answer with *one short* sentence!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q8**: When a **recursion** does **not** reach the base case, this is an example of the **early exit** strategy."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9**: Any programming language **without** looping constructs like the `for` or `while` statements is **not** Turing complete."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q10**: A **recursive** formulation is the same as a **circular** one: The terms are **synonyms**."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11**: Formulating a computational problem as a **recursion** results in an **efficient** implementation."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q12**: Whereas a **recursion** may accidentally result in a **never-ending** program, `while`-loops and `for`-loops are guaranteed to **terminate**."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13**: Before writing **any** kind of **loop**, we **always** need to think about a **stopping criterion** ahead of time."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q14**: **Container** types such as `list` objects are characterized by their **support** for **being looped over**, for example as in:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```python\n",
"for element in container:\n",
" # do something for every element\n",
" ...\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -264,6 +15,13 @@
"## Coding Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb) of the book. Then, work through the exercises below."
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -330,7 +88,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.1**: Explain for the $n = 3$ case why it can be solved as a **recursion**!"
"**Q1.1**: Explain for the $n = 3$ case why it can be solved as a **recursion**!"
]
},
{
@ -344,7 +102,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.2**: How does the number of minimal moves needed to solve a problem with three spots and $n$ disks grow as a function of $n$? How does this relate to the answer to **Q15.1**?"
"**Q1.2**: How does the number of minimal moves needed to solve a problem with three spots and $n$ disks grow as a function of $n$? How does this relate to the answer to **Q1.1**?"
]
},
{
@ -358,7 +116,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.3**: The **[Towers of Hanoi](https://en.wikipedia.org/wiki/Tower_of_Hanoi)** problem is of **exponential growth**. What does that mean? What does that imply for large $n$?"
"**Q1.3**: The **[Towers of Hanoi](https://en.wikipedia.org/wiki/Tower_of_Hanoi)** problem is of **exponential growth**. What does that mean? What does that imply for large $n$?"
]
},
{
@ -372,7 +130,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.4**: The video introduces the recursive relationship $Sol(4, 1, 3) = Sol(3, 1, 2) ~ \\bigoplus ~ Sol(1, 1, 3) ~ \\bigoplus ~ Sol(3, 2, 3)$. The $\\bigoplus$ is to be interpreted as some sort of \"plus\" operation. How does this \"plus\" operation work? How does this way of expressing the problem relate to the answer to **Q15.1**?"
"**Q1.4**: The video introduces the recursive relationship $Sol(4, 1, 3) = Sol(3, 1, 2) ~ \\bigoplus ~ Sol(1, 1, 3) ~ \\bigoplus ~ Sol(3, 2, 3)$. The $\\bigoplus$ is to be interpreted as some sort of \"plus\" operation. How does this \"plus\" operation work? How does this way of expressing the problem relate to the answer to **Q1.1**?"
]
},
{
@ -439,7 +197,7 @@
"\n",
"Once completed, `sol()` should print out all the moves in the correct order. With **printing a move**, we mean a line like \"1 -> 3\", short for \"Move the top-most disk from spot 1 to spot 3\".\n",
"\n",
"Write your answers to **Q15.5** to **Q15.7** into the subsequent code cell and finalize `sol()`! No need to write a docstring or validate the input here."
"Write your answers to **Q1.5** to **Q1.7** into the subsequent code cell and finalize `sol()`! No need to write a docstring or validate the input here."
]
},
{
@ -464,14 +222,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.5**: What is the `disks` argument when the function reaches its **base case**? Check for the base case with a simple `if` statement and return from the function using the **early exit** pattern!"
"**Q1.5**: What is the `disks` argument when the function reaches its **base case**? Check for the base case with a simple `if` statement and return from the function using the **early exit** pattern!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.6**: If not in the base case, `sol()` needs to determine the `intermediate` spot given concrete `origin` and `destination` arguments. For example, if called with `origin=1` and `destination=2`, `intermediate` must be `3`.\n",
"**Q1.6**: If not in the base case, `sol()` needs to determine the `intermediate` spot given concrete `origin` and `destination` arguments. For example, if called with `origin=1` and `destination=2`, `intermediate` must be `3`.\n",
"\n",
"Add **one** compound `if` statement to `sol()` that has a branch for **every** possible `origin`-`destination` pair that sets a variable `intermediate` to the correct temporary spot. **How many** branches will there be?"
]
@ -480,7 +238,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.7**: `sol()` needs to call itself **two more times** with the correct 2-pairs chosen from the three available spots `origin`, `intermediate`, and `destination`.\n",
"**Q1.7**: `sol()` needs to call itself **two more times** with the correct 2-pairs chosen from the three available spots `origin`, `intermediate`, and `destination`.\n",
"\n",
"In between the two recursive function calls, write a `print()` statement that prints out from where to where the \"remaining and largest\" disk has to be moved!"
]
@ -489,7 +247,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.8**: Execute the code cells below and confirm that the printed moves are correct!"
"**Q1.8**: Execute the code cells below and confirm that the printed moves are correct!"
]
},
{
@ -543,7 +301,7 @@
"\n",
"Let's create a more concise `hanoi()` function that, in addition to a positional `disks` argument, takes three keyword-only arguments `origin`, `intermediate`, and `destination` with default values `\"left\"`, `\"center\"`, and `\"right\"`.\n",
"\n",
"Write your answers to **Q15.9** and **Q15.10** into the subsequent code cell and finalize `hanoi()`! No need to write a docstring or validate the input here."
"Write your answers to **Q1.9** and **Q1.10** into the subsequent code cell and finalize `hanoi()`! No need to write a docstring or validate the input here."
]
},
{
@ -565,14 +323,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.9**: Copy the base case from `sol()`!"
"**Q1.9**: Copy the base case from `sol()`!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.10**: Instead of conditional logic, `hanoi()` calls itself **two times** with the **three** arguments `origin`, `intermediate`, and `destination` passed on in a **different** order.\n",
"**Q1.10**: Instead of conditional logic, `hanoi()` calls itself **two times** with the **three** arguments `origin`, `intermediate`, and `destination` passed on in a **different** order.\n",
"\n",
"Figure out how the arguments are passed on in the two recursive `hanoi()` calls!\n",
"\n",
@ -583,7 +341,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.11**: Execute the code cells below and confirm that the printed moves are correct!"
"**Q1.11**: Execute the code cells below and confirm that the printed moves are correct!"
]
},
{
@ -653,11 +411,11 @@
"\n",
"In such cases, we could modify a recursive function to return a count value to be passed up the recursion tree.\n",
"\n",
"This is similar to what we do in the recursive versions of `factorial()` and `fibonacci()` in [Chapter 4](https://github.com/webartifex/intro-to-python/blob/master/04_iteration.ipynb), where we pass up an intermediate result.\n",
"This is similar to what we do in the recursive versions of `factorial()` and `fibonacci()` in [Chapter 4](https://github.com/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb), where we pass up an intermediate result.\n",
"\n",
"Let's create a `hanoi_moves()` function that follows the same internal logic as `hanoi()`, but, instead of printing out the moves, returns the number of steps done so far in the recursion.\n",
"\n",
"Write your answers to **Q15.12** to **Q15.14** into the subsequent code cell and finalize `hanoi_moves()`! No need to write a docstring or validate the input here."
"Write your answers to **Q1.12** to **Q1.14** into the subsequent code cell and finalize `hanoi_moves()`! No need to write a docstring or validate the input here."
]
},
{
@ -682,21 +440,21 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.12**: Copy the base case from `hanoi()`! What count should be returned when it is reached?"
"**Q1.12**: Copy the base case from `hanoi()`! What count should be returned when it is reached?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.13**: Initialize the variable `moves` with an appropriate count! This is the number of moves that corresponds to **one** recursive function call."
"**Q1.13**: Initialize the variable `moves` with an appropriate count! This is the number of moves that corresponds to **one** recursive function call."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.14**: `moves` is updated with the counts passed up from the two recursive calls.\n",
"**Q1.14**: `moves` is updated with the counts passed up from the two recursive calls.\n",
"\n",
"Complete the two recursive function calls with the same arguments as in `hanoi()`!"
]
@ -705,7 +463,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.15**: Write a `for`-loop that prints out the **minimum number** of moves needed to solve Towers of Hanoi for any number of `disks` from `1` through `20` to confirm your answer to **Q15.2**."
"**Q1.15**: Write a `for`-loop that prints out the **minimum number** of moves needed to solve Towers of Hanoi for any number of `disks` from `1` through `20` to confirm your answer to **Q1.2**."
]
},
{
@ -733,7 +491,7 @@
"\n",
"With `disks` in the range from `24` through `26`, the computation time roughly doubles for each increase of `disks` by 1.\n",
"\n",
"**Q15.16**: Execute the code cells below and see for yourself!"
"**Q1.16**: Execute the code cells below and see for yourself!"
]
},
{
@ -779,7 +537,7 @@
"source": [
"The above `hanoi()` prints the optimal solution's moves in the correct order but fails to label each move with an order number. This can be built in by passing on one more argument `offset` down the recursion tree. As the logic gets a bit \"involved,\" `hanoi_ordered()` below is almost finished.\n",
"\n",
"Write your answers to **Q15.17** and **Q15.18** into the subsequent code cell and finalize `hanoi_ordered()`! No need to write a docstring or validate the input here."
"Write your answers to **Q1.17** and **Q1.18** into the subsequent code cell and finalize `hanoi_ordered()`! No need to write a docstring or validate the input here."
]
},
{
@ -809,14 +567,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.17**: Copy the base case from the original `hanoi()`!"
"**Q1.17**: Copy the base case from the original `hanoi()`!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.18**: Complete the two recursive function calls with the same arguments as in `hanoi()` or `hanoi_moves()`! Do not change the already filled in `offset` arguments!\n",
"**Q1.18**: Complete the two recursive function calls with the same arguments as in `hanoi()` or `hanoi_moves()`! Do not change the already filled in `offset` arguments!\n",
"\n",
"Then, copy the `print()` statement from `hanoi()` and adjust it to print out `count` as well!"
]
@ -825,7 +583,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.19**: Execute the code cells below and confirm that the order numbers are correct!"
"**Q1.19**: Execute the code cells below and confirm that the order numbers are correct!"
]
},
{
@ -882,7 +640,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15.20**: Conducting your own research on the internet (max. 15 minutes), what can you say about generalizing the **[Towers of Hanoi](https://en.wikipedia.org/wiki/Tower_of_Hanoi)** problem to a setting with **more than three** landing spots?"
"**Q1.20**: Conducting your own research on the internet (max. 15 minutes), what can you say about generalizing the **[Towers of Hanoi](https://en.wikipedia.org/wiki/Tower_of_Hanoi)** problem to a setting with **more than three** landing spots?"
]
},
{
@ -909,7 +667,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
@ -926,5 +684,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

File diff suppressed because it is too large Load diff

347
05_numbers_10_review.ipynb Normal file
View file

@ -0,0 +1,347 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Chapter 5: Bits & Numbers"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Content Review"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers_00_content.ipynb) of the book. Then, work through the questions below."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Essay Questions "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions briefly with *at most* 300 characters per question!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1**: In what way is the **binary representation** of `int` objects *similar* to the **decimal system** taught in elementary school?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q2**: Why may objects of type `bool` be regarded a **numeric type** as well?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3**: Why is it *inefficient* to store `bool` objects in bits resembling a **hexadecimal representation**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q4**: Colors are commonly expressed in the **hexadecimal system** in websites (cf., the [HTML](https://en.wikipedia.org/wiki/HTML) and [CSS](https://en.wikipedia.org/wiki/Cascading_Style_Sheets) formats).\n",
"\n",
"For example, $#000000$, $#ff9900$, and $#ffffff$ turn out to be black, orange, and white. The six digits are read in *pairs of two* from left to right, and the *three pairs* correspond to the proportions of red, green, and blue mixed together. They reach from $0_{16} = 0_{10}$ for $0$% to $\\text{ff}_{16} = 255_{10}$ for $100$% (cf., this [article](https://en.wikipedia.org/wiki/RGB_color_model) for an in-depth discussion).\n",
"\n",
"In percent, what are the proportions of red, green, and blue that make up orange? Calculate the three percentages separately! How many **bytes** are needed to encode a color? How many **bits** are that?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q5**: What does it mean for a code fragment to **fail silently**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q6**: Explain why the mathematical set of all real numbers $\\mathbb{R}$ can only be **approximated** by floating-point numbers on a computer!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7**: How do we deal with a `float` object's imprecision if we need to **check for equality**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q8**: What data type, built-in or from the [standard library](https://docs.python.org/3/library/index.html), is best suited to represent the [transcendental numbers](https://en.wikipedia.org/wiki/Transcendental_number) $\\pi$ and $\\text{e}$?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9**: How can **abstract base classes**, for example, as defined in the **numerical tower**, be helpful in enabling **duck typing**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### True / False Questions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Motivate your answer with *one short* sentence!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q10**: The precision of `int` objects depends on how we choose to represent them in memory. For example, using a **hexadecimal representation** gives us $16^8$ digits whereas with a **binary representation** an `int` object can have *at most* $2^8$ digits."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11**: With the built-in [round()](https://docs.python.org/3/library/functions.html#round) function, we obtain a *precise* representation for any `float` object if we can live with *less than* $15$ digits of precision."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q12**: As most currencies operate with $2$ or $3$ decimals (e.g., EUR $9.99$), the `float` type's limitation of *at most* $15$ digits is *not* a problem in practice."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13**: The [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) standard's **special values** provide no benefit in practice as we could always use a **[sentinel](https://en.wikipedia.org/wiki/Sentinel_value)** value (i.e., a \"dummy\"). For example, instead of `nan`, we can always use `0` to indicate a *missing* value."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q14**: The following code fragment raises an `InvalidOperation` exception. That is an example of code **failing loudly**.\n",
"```python\n",
"float(\"inf\") + float(\"-inf\")\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15**: Python provides a `scientific` type (e.g., `1.23e4`) that is useful mainly to model problems in the domains of physics or astrophysics."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q16**: From a practitioner's point of view, the built-in [format()](https://docs.python.org/3/library/functions.html#format) function does the *same* as the built-in [round()](https://docs.python.org/3/library/functions.html#round) function."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q17**: The `Decimal` type from the [decimal](https://docs.python.org/3/library/decimal.html) module in the [standard library](https://docs.python.org/3/library/index.html) allows us to model the set of the real numbers $\\mathbb{R}$ *precisely*."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q18**: The `Fraction` type from the [fractions](https://docs.python.org/3/library/fractions.html) module in the [standard library](https://docs.python.org/3/library/index.html) allows us to model the set of the rational numbers $\\mathbb{Q}$ *precisely*."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View file

@ -0,0 +1,412 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Chapter 5: Bits & Numbers"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Coding Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers_00_content.ipynb) of the book. Then, work through the exercises below."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Discounting Customer Orders (revisited)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1** in [Chapter 2's Exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_20_exercises.ipynb#Volume-of-a-Sphere) section already revealed that we must consider the effects of the `float` type's imprecision.\n",
"\n",
"This becomes even more important when we deal with numeric data modeling accounting or finance data (cf., [this comment](https://stackoverflow.com/a/24976426) on \"falsehoods programmers believe about money\").\n",
"\n",
"In addition to the *inherent imprecision* of numbers in general, the topic of **[rounding numbers](https://en.wikipedia.org/wiki/Rounding)** is also not as trivial as we might expect! [This article](https://realpython.com/python-rounding/) summarizes everything the data science practitioner needs to know.\n",
"\n",
"In this exercise, we revisit **Q1** from [Chapter 3's Exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_20_exercises.ipynb#Discounting-Customer-Orders) section, and make the `discounted_price()` function work *correctly* for real-life sales data."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.1**: Execute the code cells below! What results would you have *expected*, and why?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"round(1.5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"round(2.5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"round(2.675, 2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.2**: The built-in [round()](https://docs.python.org/3/library/functions.html#round) function implements the \"**[round half to even](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even)**\" strategy. Describe in one or two sentences what that means!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.3**: For the revised `discounted_price()` function, we have to tackle *two* issues: First, we have to replace the built-in `float` type with a data type that allows us to control the precision. Second, the discounted price should be rounded according to a more human-friendly rounding strategy, namely \"**[round half away from zero](https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero)**.\"\n",
"\n",
"Describe in one or two sentences how \"**[round half away from zero](https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero)**\" is more in line with how humans think of rounding!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.4**: We use the `Decimal` type from the [decimal](https://docs.python.org/3/library/decimal.html) module in the [standard library](https://docs.python.org/3/library/index.html) to tackle *both* issues simultaneously.\n",
"\n",
"Assign `euro` a numeric object such that both `Decimal(\"1.5\")` and `Decimal(\"2.5\")` are rounded to `Decimal(\"2\")` (i.e., no decimal) with the [quantize()](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) method!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from decimal import Decimal"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"euro = ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Decimal(\"1.5\").quantize(...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Decimal(\"2.5\").quantize(...)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.5**: Obviously, the two preceding code cells still [round half to even](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even).\n",
"\n",
"The [decimal](https://docs.python.org/3/library/decimal.html) module defines a `ROUND_HALF_UP` flag that we can pass as the second argument to the [quantize()](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) method. Then, it [rounds half away from zero](https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero).\n",
"\n",
"Add `ROUND_HALF_UP` to the code cells! `Decimal(\"2.5\")` should now be rounded to `Decimal(\"3\")`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from decimal import ROUND_HALF_UP"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Decimal(\"1.5\").quantize(...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Decimal(\"2.5\").quantize(...)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.6**: Instead of `euro`, define `cents` such that rounding occurs to *two* decimals! `Decimal(\"2.675\")` should now be rounded to `Decimal(\"2.68\")`. Do *not* forget to include the `ROUND_HALF_UP` flag!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"cents = ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Decimal(\"2.675\").quantize(...)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.7**: Rewrite the function `discounted_price()` from [Chapter 3's Exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_20_exercises.ipynb#Discounting-Customer-Orders) section!\n",
"\n",
"It takes the *positional* arguments `unit_price` and `quantity` and implements a discount scheme for a line item in a customer order as follows:\n",
"\n",
"- if the unit price is over 100 dollars, grant 10% relative discount\n",
"- if a customer orders more than 10 items, one in every five items is for free\n",
"\n",
"Only one of the two discounts is granted, whichever is better for the customer.\n",
"\n",
"The function then returns the overall price for the line item as a `Decimal` number with a precision of *two* decimals.\n",
"\n",
"Enable **duck typing** by allowing the function to be called with various numeric types as the arguments, in particular, `quantity` may be a non-integer as well: Use an appropriate **abstract base class** from the [numbers](https://docs.python.org/3/library/numbers.html) module in the [standard library](https://docs.python.org/3/library/index.html) to verify the arguments' types and also that they are both positive!\n",
"\n",
"It is considered a *best practice* to only round towards the *end* of the calculations."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numbers"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def discounted_price(...):\n",
" ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1.8**: Execute the code cells below and verify the final price for the following four test cases:\n",
"\n",
"- $7$ smartphones @ $99.00$ USD\n",
"- $3$ workstations @ $999.00$ USD\n",
"- $19$ GPUs @ $879.95$ USD\n",
"- $14$ Raspberry Pis @ $35.00$ USD\n",
"\n",
"The output should now *always* be a `Decimal` number with *two* decimals!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(99, 7)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(999, 3)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(879.95, 19)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(35, 14)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This also works if `quantity` is passed in as a `float` type."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(99, 7.0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Decimals beyond the first two are gracefully discarded (i.e., *without* rounding errors accumulating)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(99.0001, 7)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The basic input validation ensures that the user of `discounted_price()` does not pass in invalid data. Here, the `\"abc\"` creates a `TypeError`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(\"abc\", 7)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A `-1` passed in as `unit_price` results in a `ValueError`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(-1, 7)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View file

@ -1,706 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Chapter 5: Bits & Numbers"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Content Review"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers.ipynb) of the book. Then work through the eighteen review questions."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Essay Questions "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions briefly with *at most* 300 characters per question!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1**: In what way is the **binary representation** of `int` objects *similar* to the **decimal system** taught in elementary school?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q2**: Why may objects of type `bool` be regarded a **numeric type** as well?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3**: Why is it *inefficient* to store `bool` objects in bits resembling a **hexadecimal representation**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q4**: Colors are commonly expressed in the **hexadecimal system** in websites (cf., the [HTML](https://en.wikipedia.org/wiki/HTML) and [CSS](https://en.wikipedia.org/wiki/Cascading_Style_Sheets) formats).\n",
"\n",
"For example, $#000000$, $#ff9900$, and $#ffffff$ turn out to be black, orange, and white. The six digits are read in *pairs of two* from left to right, and the *three pairs* correspond to the proportions of red, green, and blue mixed together. They reach from $0_{16} = 0_{10}$ for $0$% to $\\text{ff}_{16} = 255_{10}$ for $100$% (cf., this [article](https://en.wikipedia.org/wiki/RGB_color_model) for an in-depth discussion).\n",
"\n",
"In percent, what are the proportions of red, green, and blue that make up orange? Calculate the three percentages separately! How many **bytes** are needed to encode a color? How many **bits** are that?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q5**: What does it mean for a code fragment to **fail silently**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q6**: Explain why the mathematical set of all real numbers $\\mathbb{R}$ can only be **approximated** by floating-point numbers on a computer!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7**: How do we deal with a `float` object's imprecision if we need to **check for equality**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q8**: What data type, built-in or from the [standard library](https://docs.python.org/3/library/index.html), is best suited to represent the [transcendental numbers](https://en.wikipedia.org/wiki/Transcendental_number) $\\pi$ and $\\text{e}$?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9**: How can **abstract base classes**, for example, as defined in the **numerical tower**, be helpful in enabling **duck typing**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### True / False Questions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Motivate your answer with *one short* sentence!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q10**: The precision of `int` objects depends on how we choose to represent them in memory. For example, using a **hexadecimal representation** gives us $16^8$ digits whereas with a **binary representation** an `int` object can have *at most* $2^8$ digits."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11**: With the built-in [round()](https://docs.python.org/3/library/functions.html#round) function, we obtain a *precise* representation for any `float` object if we can live with *less than* $15$ digits of precision."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q12**: As most currencies operate with $2$ or $3$ decimals (e.g., EUR $9.99$), the `float` type's limitation of *at most* $15$ digits is *not* a problem in practice."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13**: The [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) standard's **special values** provide no benefit in practice as we could always use a **[sentinel](https://en.wikipedia.org/wiki/Sentinel_value)** value (i.e., a \"dummy\"). For example, instead of `nan`, we can always use `0` to indicate a *missing* value."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q14**: The following code fragment raises an `InvalidOperation` exception. That is an example of code **failing loudly**.\n",
"```python\n",
"float(\"inf\") + float(\"-inf\")\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15**: Python provides a `scientific` type (e.g., `1.23e4`) that is useful mainly to model problems in the domains of physics or astrophysics."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q16**: From a practitioner's point of view, the built-in [format()](https://docs.python.org/3/library/functions.html#format) function does the *same* as the built-in [round()](https://docs.python.org/3/library/functions.html#round) function."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q17**: The `Decimal` type from the [decimal](https://docs.python.org/3/library/decimal.html) module in the [standard library](https://docs.python.org/3/library/index.html) allows us to model the set of the real numbers $\\mathbb{R}$ *precisely*."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q18**: The `Fraction` type from the [fractions](https://docs.python.org/3/library/fractions.html) module in the [standard library](https://docs.python.org/3/library/index.html) allows us to model the set of the rational numbers $\\mathbb{Q}$ *precisely*."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Coding Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Discounting Customer Orders (revisited)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11** in [Chapter 2's Review & Exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_review_and_exercises.ipynb#Volume-of-a-Sphere) section already revealed that we must consider the effects of the `float` type's imprecision.\n",
"\n",
"This becomes even more important when we deal with numeric data modeling accounting or finance data (cf., [this comment](https://stackoverflow.com/a/24976426) on \"falsehoods programmers believe about money\").\n",
"\n",
"In addition to the *inherent imprecision* of numbers in general, the topic of **[rounding numbers](https://en.wikipedia.org/wiki/Rounding)** is also not as trivial as we might expect! [This article](https://realpython.com/python-rounding/) summarizes everything the data science practitioner needs to know.\n",
"\n",
"In this exercise, we revisit **Q9** from [Chapter 3's Review & Exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_review_and_exercises.ipynb#Discounting-Customer-Orders) section, and make the `discounted_price()` function work *correctly* for real-life sales data."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q19.1**: Execute the code cells below! What results would you have *expected*, and why?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"round(1.5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"round(2.5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"round(2.675, 2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q19.2**: The built-in [round()](https://docs.python.org/3/library/functions.html#round) function implements the \"**[round half to even](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even)**\" strategy. Describe in one or two sentences what that means!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q19.3**: For the revised `discounted_price()` function, we have to tackle *two* issues: First, we have to replace the built-in `float` type with a data type that allows us to control the precision. Second, the discounted price should be rounded according to a more human-friendly rounding strategy, namely \"**[round half away from zero](https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero)**.\"\n",
"\n",
"Describe in one or two sentences how \"**[round half away from zero](https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero)**\" is more in line with how humans think of rounding!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q19.4**: We use the `Decimal` type from the [decimal](https://docs.python.org/3/library/decimal.html) module in the [standard library](https://docs.python.org/3/library/index.html) to tackle *both* issues simultaneously.\n",
"\n",
"Assign `euro` a numeric object such that both `Decimal(\"1.5\")` and `Decimal(\"2.5\")` are rounded to `Decimal(\"2\")` (i.e., no decimal) with the [quantize()](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) method!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from decimal import Decimal"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"euro = ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Decimal(\"1.5\").quantize(...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Decimal(\"2.5\").quantize(...)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q19.5**: Obviously, the two preceding code cells still [round half to even](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even).\n",
"\n",
"The [decimal](https://docs.python.org/3/library/decimal.html) module defines a `ROUND_HALF_UP` flag that we can pass as the second argument to the [quantize()](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) method. Then, it [rounds half away from zero](https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero).\n",
"\n",
"Add `ROUND_HALF_UP` to the code cells! `Decimal(\"2.5\")` should now be rounded to `Decimal(\"3\")`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from decimal import ROUND_HALF_UP"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Decimal(\"1.5\").quantize(...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Decimal(\"2.5\").quantize(...)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q19.6**: Instead of `euro`, define `cents` such that rounding occurs to *two* decimals! `Decimal(\"2.675\")` should now be rounded to `Decimal(\"2.68\")`. Do *not* forget to include the `ROUND_HALF_UP` flag!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"cents = ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Decimal(\"2.675\").quantize(...)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q19.7**: Rewrite the function `discounted_price()` from [Chapter 3's Review & Exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_review_and_exercises.ipynb#Discounting-Customer-Orders) section!\n",
"\n",
"It takes the *positional* arguments `unit_price` and `quantity` and implements a discount scheme for a line item in a customer order as follows:\n",
"\n",
"- if the unit price is over 100 dollars, grant 10% relative discount\n",
"- if a customer orders more than 10 items, one in every five items is for free\n",
"\n",
"Only one of the two discounts is granted, whichever is better for the customer.\n",
"\n",
"The function then returns the overall price for the line item as a `Decimal` number with a precision of *two* decimals.\n",
"\n",
"Enable **duck typing** by allowing the function to be called with various numeric types as the arguments, in particular, `quantity` may be a non-integer as well: Use an appropriate **abstract base class** from the [numbers](https://docs.python.org/3/library/numbers.html) module in the [standard library](https://docs.python.org/3/library/index.html) to verify the arguments' types and also that they are both positive!\n",
"\n",
"It is considered a *best practice* to only round towards the *end* of the calculations."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numbers"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def discounted_price(...):\n",
" ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q19.8**: Execute the code cells below and verify the final price for the following four test cases:\n",
"\n",
"- $7$ smartphones @ $99.00$ USD\n",
"- $3$ workstations @ $999.00$ USD\n",
"- $19$ GPUs @ $879.95$ USD\n",
"- $14$ Raspberry Pis @ $35.00$ USD\n",
"\n",
"The output should now *always* be a `Decimal` number with *two* decimals!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(99, 7)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(999, 3)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(879.95, 19)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(35, 14)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This also works if `quantity` is passed in as a `float` type."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(99, 7.0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Decimals beyond the first two are gracefully discarded (i.e., *without* rounding errors accumulating)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(99.0001, 7)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The basic input validation ensures that the user of `discounted_price()` does not pass in invalid data. Here, the `\"abc\"` creates a `TypeError`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(\"abc\", 7)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A `-1` passed in as `unit_price` results in a `ValueError`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"discounted_price(-1, 7)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because it is too large Load diff

View file

@ -19,7 +19,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 6](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text.ipynb) of the book. Then work through the eight review questions."
"Read [Chapter 6](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text_00_content.ipynb) of the book. Then, work through the questions below."
]
},
{
@ -33,7 +33,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions briefly with *at most* 300 characters per question!"
"Answer the following questions *briefly*!"
]
},
{
@ -184,7 +184,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
@ -201,5 +201,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View file

@ -19,11 +19,11 @@
}
},
"source": [
"We studied numbers (cf., [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers.ipynb)) and textual data (cf., [Chapter 6](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text.ipynb)) first, mainly because objects of the presented data types are \"simple,\" for two reasons: First, they are *immutable*, and, as we saw in the \"*Who am I? And how many?*\" section in [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb#Who-am-I?-And-how-many?), mutable objects can quickly become hard to reason about. Second, they are \"flat\" in the sense that they are *not* composed of other objects.\n",
"We studied numbers (cf., [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers_00_content.ipynb)) and textual data (cf., [Chapter 6](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text_00_content.ipynb)) first, mainly because objects of the presented data types are \"simple,\" for two reasons: First, they are *immutable*, and, as we saw in the \"*Who am I? And how many?*\" section in [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_content.ipynb#Who-am-I?-And-how-many?), mutable objects can quickly become hard to reason about. Second, they are \"flat\" in the sense that they are *not* composed of other objects.\n",
"\n",
"The `str` type is a bit of a corner case in this regard. While one could argue that a longer `str` object, for example, `\"text\"`, is composed of individual characters, this is *not* the case in memory as the literal `\"text\"` only creates *one* object (i.e., one \"bag\" of $0$s and $1$s modeling all characters).\n",
"\n",
"This chapter and [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings.ipynb) introduce various \"complex\" data types. While some are mutable and others are not, they all share that they are primarily used to \"manage,\" or structure, the memory in a program. Unsurprisingly, computer scientists refer to the ideas and theories behind these data types as **[data structures](https://en.wikipedia.org/wiki/Data_structure)**.\n",
"This chapter, [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings_00_content.ipynb), and [Chapter 9](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/09_arrays_00_content.ipynb) introduce various \"complex\" data types. While some are mutable and others are not, they all share that they are primarily used to \"manage,\" or structure, the memory in a program. Unsurprisingly, computer scientists refer to the ideas and theories behind these data types as **[data structures](https://en.wikipedia.org/wiki/Data_structure)**.\n",
"\n",
"In this chapter, we focus on data types that model all kinds of sequential data. Examples of such data are [spreadsheets](https://en.wikipedia.org/wiki/Spreadsheet) or [matrices](https://en.wikipedia.org/wiki/Matrix_%28mathematics%29)/[vectors](https://en.wikipedia.org/wiki/Vector_%28mathematics_and_physics%29). Such formats share the property that they are composed of smaller units that come in a sequence of, for example, rows/columns/cells or elements/entries."
]
@ -47,9 +47,9 @@
}
},
"source": [
"[Chapter 6](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text.ipynb#A-\"String\"-of-Characters) already describes the *sequence* properties of `str` objects. Here, we take a step back and study these properties on their own before looking at bigger ideas.\n",
"[Chapter 6](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text_00_content.ipynb#A-\"String\"-of-Characters) already describes the *sequence* properties of `str` objects. Here, we take a step back and study these properties on their own before looking at bigger ideas.\n",
"\n",
"The [collections.abc](https://docs.python.org/3/library/collections.abc.html) module in the [standard library](https://docs.python.org/3/library/index.html) defines a variety of **abstract base classes** (ABCs). We saw ABCs already in [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers.ipynb#The-Numerical-Tower), where we use the ones from the [numbers](https://docs.python.org/3/library/numbers.html) module in the [standard library](https://docs.python.org/3/library/index.html) to classify Python's numeric data types according to mathematical ideas. Now, we take the ABCs from the [collections.abc](https://docs.python.org/3/library/collections.abc.html) module to classify the data types in this chapter and [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings.ipynb) according to their behavior in various contexts.\n",
"The [collections.abc](https://docs.python.org/3/library/collections.abc.html) module in the [standard library](https://docs.python.org/3/library/index.html) defines a variety of **abstract base classes** (ABCs). We saw ABCs already in [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers_00_content.ipynb#The-Numerical-Tower), where we use the ones from the [numbers](https://docs.python.org/3/library/numbers.html) module in the [standard library](https://docs.python.org/3/library/index.html) to classify Python's numeric data types according to mathematical ideas. Now, we take the ABCs from the [collections.abc](https://docs.python.org/3/library/collections.abc.html) module to classify the data types in this chapter and [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings_00_content.ipynb) according to their behavior in various contexts.\n",
"\n",
"As an illustration, consider `numbers` and `text` below, two objects of *different* types."
]
@ -65,7 +65,7 @@
"outputs": [],
"source": [
"numbers = [7, 11, 8, 5, 3, 12, 2, 6, 9, 10, 1, 4]\n",
"text = \"Lorem ipsum dolor sit amet, consectetur ...\""
"text = \"Lorem ipsum dolor sit amet, ...\""
]
},
{
@ -114,7 +114,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"L o r e m i p s u m d o l o r s i t a m e t , c o n s e c t e t u r . . . "
"L o r e m i p s u m d o l o r s i t a m e t , . . . "
]
}
],
@ -131,7 +131,7 @@
}
},
"source": [
"In [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb#Containers-vs.-Iterables), we referred to such types as *iterables*. That is *not* a proper [English](https://dictionary.cambridge.org/spellcheck/english-german/?q=iterable) word, even if it may sound like one at first sight. Yet, it is an official term in the Python world formalized with the `Iterable` ABC in the [collections.abc](https://docs.python.org/3/library/collections.abc.html) module.\n",
"In [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb#Containers-vs.-Iterables), we referred to such types as *iterables*. That is *not* a proper [English](https://dictionary.cambridge.org/spellcheck/english-german/?q=iterable) word, even if it may sound like one at first sight. Yet, it is an official term in the Python world formalized with the `Iterable` ABC in the [collections.abc](https://docs.python.org/3/library/collections.abc.html) module.\n",
"\n",
"For the data science practitioner, it is worthwhile to know such terms as, for example, the documentation on the [built-ins](https://docs.python.org/3/library/functions.html) uses them extensively: In simple words, any built-in that takes an argument called \"*iterable*\" may be called with *any* object that supports being looped over. Already familiar [built-ins](https://docs.python.org/3/library/functions.html) include [enumerate()](https://docs.python.org/3/library/functions.html#enumerate), [sum()](https://docs.python.org/3/library/functions.html#sum), or [zip()](https://docs.python.org/3/library/functions.html#zip). So, they do *not* require the argument to be of a certain data type (e.g., `list`); instead, any *iterable* type works."
]
@ -181,7 +181,7 @@
}
},
"source": [
"As in the context of *goose typing* in [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers.ipynb#Goose-Typing), we can use ABCs with the built-in [isinstance()](https://docs.python.org/3/library/functions.html#isinstance) function to check if an object supports a behavior.\n",
"As in the context of *goose typing* in [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers_00_content.ipynb#Goose-Typing), we can use ABCs with the built-in [isinstance()](https://docs.python.org/3/library/functions.html#isinstance) function to check if an object supports a behavior.\n",
"\n",
"So, let's \"ask\" Python if it can loop over `numbers` or `text`."
]
@ -536,7 +536,7 @@
{
"data": {
"text/plain": [
"43"
"31"
]
},
"execution_count": 17,
@ -767,7 +767,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
". . . r u t e t c e s n o c , t e m a t i s r o l o d m u s p i m e r o L "
". . . , t e m a t i s r o l o d m u s p i m e r o L "
]
}
],
@ -1028,7 +1028,7 @@
{
"data": {
"text/plain": [
"140157873498184"
"140417317434464"
]
},
"execution_count": 34,
@ -1074,7 +1074,7 @@
"source": [
"Alternatively, we use the [list()](https://docs.python.org/3/library/functions.html#func-list) built-in to create a `list` object out of an iterable we pass to it as the argument.\n",
"\n",
"For example, we can wrap the [range()](https://docs.python.org/3/library/functions.html#func-range) built-in with [list()](https://docs.python.org/3/library/functions.html#func-list): As described in [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb#Containers-vs.-Iterables), `range` objects, like `range(1, 13)` below, are iterable and generate `int` objects \"on the fly\" (i.e., one by one). The [list()](https://docs.python.org/3/library/functions.html#func-list) around it acts like a `for`-loop and **materializes** twelve `int` objects in memory that then become the elements of the newly created `list` object. [PythonTutor](http://www.pythontutor.com/visualize.html#code=r%20%3D%20range%281,%2013%29%0Al%20%3D%20list%28range%281,%2013%29%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) shows this difference visually."
"For example, we can wrap the [range()](https://docs.python.org/3/library/functions.html#func-range) built-in with [list()](https://docs.python.org/3/library/functions.html#func-list): As described in [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb#Containers-vs.-Iterables), `range` objects, like `range(1, 13)` below, are iterable and generate `int` objects \"on the fly\" (i.e., one by one). The [list()](https://docs.python.org/3/library/functions.html#func-list) around it acts like a `for`-loop and **materializes** twelve `int` objects in memory that then become the elements of the newly created `list` object. [PythonTutor](http://www.pythontutor.com/visualize.html#code=r%20%3D%20range%281,%2013%29%0Al%20%3D%20list%28range%281,%2013%29%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) shows this difference visually."
]
},
{
@ -1299,11 +1299,11 @@
"name": "stdout",
"output_type": "stream",
"text": [
"[] \t140157882223304 \t<class 'list'>\n",
"10 \t93987402609984 \t<class 'int'>\n",
"20.0 \t140157882328912 \t<class 'float'>\n",
"Thirty \t140157873509520 \t<class 'str'>\n",
"[40, 50] \t140157873031176 \t<class 'list'>\n"
"[] \t140417315676720 \t<class 'list'>\n",
"10 \t94860849595456 \t<class 'int'>\n",
"20.0 \t140417316476784 \t<class 'float'>\n",
"Thirty \t140417315739568 \t<class 'str'>\n",
"[40, 50] \t140417315720800 \t<class 'list'>\n"
]
}
],
@ -2017,7 +2017,7 @@
{
"data": {
"text/plain": [
"140157882223304"
"140417315676720"
]
},
"execution_count": 65,
@ -2041,7 +2041,7 @@
{
"data": {
"text/plain": [
"140157882223304"
"140417315676720"
]
},
"execution_count": 66,
@ -2065,7 +2065,7 @@
{
"data": {
"text/plain": [
"140157882223304"
"140417315676720"
]
},
"execution_count": 67,
@ -2191,7 +2191,7 @@
{
"data": {
"text/plain": [
"140157882223304"
"140417315676720"
]
},
"execution_count": 72,
@ -2215,7 +2215,7 @@
{
"data": {
"text/plain": [
"140157873029448"
"140417376809600"
]
},
"execution_count": 73,
@ -2392,7 +2392,7 @@
{
"data": {
"text/plain": [
"140157873498184"
"140417317434464"
]
},
"execution_count": 79,
@ -2401,7 +2401,7 @@
}
],
"source": [
"id(nested)"
"id(nested) # same memory location as before"
]
},
{
@ -2678,7 +2678,7 @@
"source": [
"The `list` type is an essential data structure in any real-world Python application, and many typical `list`-related algorithms from computer science theory are already built into it at the C level (cf., the [documentation](https://docs.python.org/3/library/stdtypes.html#mutable-sequence-types) or the [tutorial](https://docs.python.org/3/tutorial/datastructures.html#more-on-lists) for a full overview; unfortunately, not all methods have direct links). So, understanding and applying the built-in methods of the `list` type not only speeds up the development process but also makes programs significantly faster.\n",
"\n",
"In contrast to the `str` type's methods in [Chapter 6](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text.ipynb#String-Methods) (e.g., [upper()](https://docs.python.org/3/library/stdtypes.html#str.upper) or [lower()](https://docs.python.org/3/library/stdtypes.html#str.lower)), the `list` type's methods that mutate an object do so *in place*. That means they *never* create *new* `list` objects and return `None` to indicate that. So, we must *never* assign the return value of `list` methods to the variable holding the list!\n",
"In contrast to the `str` type's methods in [Chapter 6](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text_00_content.ipynb#String-Methods) (e.g., [upper()](https://docs.python.org/3/library/stdtypes.html#str.upper) or [lower()](https://docs.python.org/3/library/stdtypes.html#str.lower)), the `list` type's methods that mutate an object do so *in place*. That means they *never* create *new* `list` objects and return `None` to indicate that. So, we must *never* assign the return value of `list` methods to the variable holding the list!\n",
"\n",
"Let's look at the following `names` example."
]
@ -3016,7 +3016,7 @@
"source": [
"The [sort()](https://docs.python.org/3/library/stdtypes.html#list.sort) method and the [sorted()](https://docs.python.org/3/library/functions.html#sorted) function sort the elements in `names` in alphabetical order, forward or backward. However, that does *not* hold in general.\n",
"\n",
"We mention above that `list` objects may contain objects of *any* type and even of *mixed* types. Because of that, the sorting is **[delegated](https://en.wikipedia.org/wiki/Delegation_(object-oriented_programming))** to the elements in a `list` object. In a way, Python \"asks\" the elements in a `list` object to sort themselves. As `names` contains only `str` objects, they are sorted according the the comparison rules explained in [Chapter 6](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text.ipynb#String-Comparison).\n",
"We mention above that `list` objects may contain objects of *any* type and even of *mixed* types. Because of that, the sorting is **[delegated](https://en.wikipedia.org/wiki/Delegation_(object-oriented_programming))** to the elements in a `list` object. In a way, Python \"asks\" the elements in a `list` object to sort themselves. As `names` contains only `str` objects, they are sorted according the the comparison rules explained in [Chapter 6](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text_00_content.ipynb#String-Comparison).\n",
"\n",
"To customize the sorting, we pass a keyword-only `key` argument to [sort()](https://docs.python.org/3/library/stdtypes.html#list.sort) or [sorted()](https://docs.python.org/3/library/functions.html#sorted), which must be a `function` object accepting *one* positional argument. Then, the elements in the `list` object are passed to that one by one, and the return values are used as the **sort keys**. The `key` argument is also a popular use case for `lambda` expressions.\n",
"\n",
@ -4150,7 +4150,7 @@
"\n",
"The revised `add_xyz()` function below is more natural to reason about as it does *not* modify the passed in `arg` internally. This approach is following the **[functional programming](https://en.wikipedia.org/wiki/Functional_programming)** paradigm that is going through a \"renaissance\" currently. Two essential characteristics of functional programming are that a function *never* changes its inputs and *always* returns the same output given the same inputs.\n",
"\n",
"For a beginner, it is probably better to stick to this idea and not change any arguments as the original `add_xyz()` above. However, functions that modify and return the argument passed in are an important aspect of object-oriented programming, as explained in Chapter 9."
"For a beginner, it is probably better to stick to this idea and not change any arguments as the original `add_xyz()` above. However, functions that modify and return the argument passed in are an important aspect of object-oriented programming, as explained in Chapter 10."
]
},
{
@ -4511,7 +4511,7 @@
{
"data": {
"text/plain": [
"140157873009144"
"140417315626832"
]
},
"execution_count": 158,
@ -5227,7 +5227,6 @@
"cell_type": "code",
"execution_count": 184,
"metadata": {
"scrolled": false,
"slideshow": {
"slide_type": "skip"
}
@ -6154,7 +6153,7 @@
}
},
"source": [
"Unpacking allows us to rewrite the iterative `fibonacci()` function from [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb#\"Hard-at-first-Glance\"-Example:-Fibonacci-Numbers-%28revisited%29) in a concise way, now also supporting *goose typing* with the [numbers](https://docs.python.org/3/library/numbers.html) module from the [standard library](https://docs.python.org/3/library/index.html)."
"Unpacking allows us to rewrite the iterative `fibonacci()` function from [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb#\"Hard-at-first-Glance\"-Example:-Fibonacci-Numbers-%28revisited%29) in a concise way, now also supporting *goose typing* with the [numbers](https://docs.python.org/3/library/numbers.html) module from the [standard library](https://docs.python.org/3/library/index.html)."
]
},
{
@ -6577,7 +6576,7 @@
}
},
"source": [
"In the \"*Packing & Unpacking with Functions*\" [exercise](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_review_and_exercises.ipynb#Packing-&-Unpacking-with-Functions) at the end of this chapter, we look at `product()` in more detail.\n",
"In the \"*Packing & Unpacking with Functions*\" [exercise](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_review_and_exercises_00_content.ipynb#Packing-&-Unpacking-with-Functions) at the end of this chapter, we look at `product()` in more detail.\n",
"\n",
"While we needed to unpack `one_hundred` above to avoid the semantic error, unpacking an argument in a function call may also be a convenience in general.\n",
"\n",
@ -6699,7 +6698,7 @@
"source": [
"We implicitly assume that the first element represents the $x$ and the second the $y$ coordinate. While that follows intuitively from convention in math, we should at least add comments somewhere in the code to document this assumption.\n",
"\n",
"A better way is to create a *custom* data type. While that is covered in depth in Chapter 9, the [collections](https://docs.python.org/3/library/collections.html) module in the [standard library](https://docs.python.org/3/library/index.html) provides a [namedtuple()](https://docs.python.org/3/library/collections.html#collections.namedtuple) **factory function** that creates \"simple\" custom data types on top of the standard `tuple` type."
"A better way is to create a *custom* data type. While that is covered in depth in Chapter 10, the [collections](https://docs.python.org/3/library/collections.html) module in the [standard library](https://docs.python.org/3/library/index.html) provides a [namedtuple()](https://docs.python.org/3/library/collections.html#collections.namedtuple) **factory function** that creates \"simple\" custom data types on top of the standard `tuple` type."
]
},
{
@ -6762,7 +6761,7 @@
{
"data": {
"text/plain": [
"140157466523464"
"140416708056240"
]
},
"execution_count": 238,
@ -6915,7 +6914,7 @@
{
"data": {
"text/plain": [
"140157872590424"
"140417315422528"
]
},
"execution_count": 243,
@ -7354,7 +7353,7 @@
{
"data": {
"text/plain": [
"<map at 0x7f790c37f470>"
"<map at 0x7fb5743a9ad0>"
]
},
"execution_count": 258,
@ -7654,7 +7653,7 @@
{
"data": {
"text/plain": [
"<filter at 0x7f790c387c88>"
"<filter at 0x7fb57435cc10>"
]
},
"execution_count": 269,
@ -7875,7 +7874,7 @@
}
},
"source": [
"Using the [map()](https://docs.python.org/3/library/functions.html#map) and [filter()](https://docs.python.org/3/library/functions.html#filter) built-ins, we can quickly switch the order: Filter first and then transform the remaining elements. This variant equals the \"*A simple Filter*\" example from [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb#Example:-A-simple-Filter). On the contrary, code with `for`-loops and `if` statements is more tedious to adapt. Additionally, `map` and `filter` objects are optimized at the C level and, therefore, a lot faster as well."
"Using the [map()](https://docs.python.org/3/library/functions.html#map) and [filter()](https://docs.python.org/3/library/functions.html#filter) built-ins, we can quickly switch the order: Filter first and then transform the remaining elements. This variant equals the \"*A simple Filter*\" example from [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb#Example:-A-simple-Filter). On the contrary, code with `for`-loops and `if` statements is more tedious to adapt. Additionally, `map` and `filter` objects are optimized at the C level and, therefore, a lot faster as well."
]
},
{
@ -8209,7 +8208,7 @@
"\n",
"Often, such functions are used *only once* in a program. However, the primary purpose of functions is to *reuse* them. In such cases, it makes more sense to define them \"anonymously\" right at the position where the first argument goes.\n",
"\n",
"As mentioned in [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb#Anonymous-Functions), Python provides `lambda` expressions to create `function` objects *without* a name referencing them.\n",
"As mentioned in [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_00_content.ipynb#Anonymous-Functions), Python provides `lambda` expressions to create `function` objects *without* a name referencing them.\n",
"\n",
"So, the above `add()` function could be rewritten as a `lambda` expression like so ..."
]
@ -8423,7 +8422,7 @@
"source": [
"For [map()](https://docs.python.org/3/library/functions.html#map) and [filter()](https://docs.python.org/3/library/functions.html#filter), Python provides a nice syntax appealing to people who like mathematics.\n",
"\n",
"Consider again the \"*A simple Filter*\" example from [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb#Example:-A-simple-Filter), written with combined `for` and `if` statements. So, the mapping and filtering steps happen simultaneously."
"Consider again the \"*A simple Filter*\" example from [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb#Example:-A-simple-Filter), written with combined `for` and `if` statements. So, the mapping and filtering steps happen simultaneously."
]
},
{
@ -8488,7 +8487,7 @@
}
},
"source": [
"**List comprehensions**, or **list-comps** for short, are *expressions* to derive *new* `list` objects out of *existing* ones (cf., [reference](https://docs.python.org/3/reference/expressions.html#displays-for-lists-sets-and-dictionaries)). A single *expression* like below can replace the compound `for` *statement* from above."
"**List comprehensions**, or **listcomps** for short, are *expressions* to derive *new* `list` objects out of *existing* ones (cf., [reference](https://docs.python.org/3/reference/expressions.html#displays-for-lists-sets-and-dictionaries)). A single *expression* like below can replace the compound `for` *statement* from above."
]
},
{
@ -9108,7 +9107,7 @@
{
"data": {
"text/plain": [
"<generator object <genexpr> at 0x7f790c3a55e8>"
"<generator object <genexpr> at 0x7fb57436f3d0>"
]
},
"execution_count": 312,
@ -9263,7 +9262,7 @@
{
"data": {
"text/plain": [
"<generator object <genexpr> at 0x7f790c3a5a20>"
"<generator object <genexpr> at 0x7fb57436f650>"
]
},
"execution_count": 317,
@ -9728,7 +9727,7 @@
{
"data": {
"text/plain": [
"<generator object <genexpr> at 0x7f790c3a5b10>"
"<generator object <genexpr> at 0x7fb57436fad0>"
]
},
"execution_count": 333,
@ -10074,7 +10073,7 @@
}
},
"source": [
"[all()](https://docs.python.org/3/library/functions.html#all) can be viewed as syntactic sugar replacing a `for`-loop: Internally, [all()](https://docs.python.org/3/library/functions.html#all) implements the *short-circuiting* strategy from [Chapter 3](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals.ipynb#Short-Circuiting), and we mimic that by testing for the *opposite* condition in the `if` statement and leaving the `for`-loop early with the `break` statement. In the worst case, if `threshold` were, for example, `150`, we would loop over *all* elements in the *iterable*, which must be *finite* for the code to work. So, [all()](https://docs.python.org/3/library/functions.html#all) is a *linear search* in disguise."
"[all()](https://docs.python.org/3/library/functions.html#all) can be viewed as syntactic sugar replacing a `for`-loop: Internally, [all()](https://docs.python.org/3/library/functions.html#all) implements the *short-circuiting* strategy from [Chapter 3](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_00_content.ipynb#Short-Circuiting), and we mimic that by testing for the *opposite* condition in the `if` statement and leaving the `for`-loop early with the `break` statement. In the worst case, if `threshold` were, for example, `150`, we would loop over *all* elements in the *iterable*, which must be *finite* for the code to work. So, [all()](https://docs.python.org/3/library/functions.html#all) is a *linear search* in disguise."
]
},
{
@ -10388,13 +10387,13 @@
}
},
"source": [
"With the new concepts in this chapter, let's rewrite the book's introductory \"*Averaging Even Numbers*\" example in [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb#Example:-Averaging-Even-Numbers) such that it efficiently handles a large sequence of numbers.\n",
"With the new concepts in this chapter, let's rewrite the book's introductory \"*Averaging Even Numbers*\" example in [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_content.ipynb#Example:-Averaging-Even-Numbers) such that it efficiently handles a large sequence of numbers.\n",
"\n",
"We assume the `average_evens()` function below is called with a *finite* and *iterable* object, which generates a \"stream\" of numeric objects that can be cast as `int` objects because the idea of even and odd numbers only makes sense in the context of whole numbers.\n",
"\n",
"The generator expression `(int(n) for n in numbers)` implements the type casting, and when it is evaluated, *nothing* happens except that a `generator` object is stored in `integers`. Then, with the [reduce()](https://docs.python.org/3/library/functools.html#functools.reduce) function from the [functools](https://docs.python.org/3/library/functools.html) module, we *simultaneously* add up *and* count the even numbers produced by the inner generator expression `((n, 1) for n in integers if n % 2 == 0)`. That results in a `generator` object producing `tuple` objects consisting of the next *even* number in line and `1`. Two such `tuple` objects are then iteratively passed to the `lambda` expression as the `x` and `y` arguments. `x` represents the total and the count of the even numbers processed so far, while `y`'s first element, `y[0]`, is the next even number to be added to the running total. The result of the [reduce()](https://docs.python.org/3/library/functools.html#functools.reduce) function is again a `tuple` object, namely the final `total` and `count`. Lastly, we calculate the simple average.\n",
"\n",
"In summary, the implementation of `average_evens()` does *not* keep materialized `list` objects internally like its predecessors from [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb), but processes the elements of the `numbers` argument on a one-by-one basis."
"In summary, the implementation of `average_evens()` does *not* keep materialized `list` objects internally like its predecessors from [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_00_content.ipynb), but processes the elements of the `numbers` argument on a one-by-one basis."
]
},
{
@ -11014,7 +11013,7 @@
{
"data": {
"text/plain": [
"<zip at 0x7f790c318208>"
"<zip at 0x7fb57438a500>"
]
},
"execution_count": 375,
@ -11110,7 +11109,7 @@
{
"data": {
"text/plain": [
"<zip at 0x7f790c318208>"
"<zip at 0x7fb57438a500>"
]
},
"execution_count": 379,
@ -11318,7 +11317,7 @@
}
},
"source": [
"In [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb#The-for-Statement), we argue that the `for` statement is syntactic sugar, replacing the `while` statement in many scenarios. In particular, a `for`-loop saves us two tasks: Managing an index variable *and* obtaining the individual elements by indexing. In this sub-section, we look at a more realistic picture, using the new terminology as well.\n",
"In [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb#The-for-Statement), we argue that the `for` statement is syntactic sugar, replacing the `while` statement in many scenarios. In particular, a `for`-loop saves us two tasks: Managing an index variable *and* obtaining the individual elements by indexing. In this sub-section, we look at a more realistic picture, using the new terminology as well.\n",
"\n",
"Let's print out the elements of a `list` object as the *iterable* to be looped over."
]
@ -11460,7 +11459,7 @@
"source": [
"Now that we know the concept of an *iterator*, let's compare some of the built-ins introduced in this chapter in detail and make sure we understand what is going on in memory. This sub-section is thus a great summary of this chapter as well.\n",
"\n",
"We use two simple examples, `numbers` and `memoryless`, to guide us through the discussion. `numbers` creates *thirteen* objects in memory and `memoryless` only *one* (cf., [PythonTutor](http://www.pythontutor.com/visualize.html#code=numbers%20%3D%20%5B7,%2011,%208,%205,%203,%2012,%202,%206,%209,%2010,%201,%204%5D%0Amemoryless%20%3D%20range%281,%2013%29&cumulative=false&curInstr=2&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false))"
"We use two simple examples, `numbers` and `memoryless`, to guide us through the discussion. `numbers` creates *thirteen* objects in memory and `memoryless` only *one* (cf., [PythonTutor](http://www.pythontutor.com/visualize.html#code=numbers%20%3D%20%5B7,%2011,%208,%205,%203,%2012,%202,%206,%209,%2010,%201,%204%5D%0Amemoryless%20%3D%20range%281,%2013%29&cumulative=false&curInstr=2&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false))."
]
},
{
@ -11499,7 +11498,7 @@
"source": [
"The [sorted()](https://docs.python.org/3/library/functions.html#sorted) function takes a *finite* and *iterable* object as its argument and *materializes* its elements into a *new* `list` object that is returned.\n",
"\n",
"The argument may already be materialized, as is the case with `numbers`, but could also be an *iterator* that generates *new* objects, such as `memoryless`. In both cases, we end up with materialized `list` objects with the elements sorted in *forward* order (cf., [PythonTutor](http://www.pythontutor.com/visualize.html#code=numbers%20%3D%20%5B7,%2011,%208,%205,%203,%2012,%202,%206,%209,%2010,%201,%204%5D%0Amemoryless%20%3D%20range%281,%2013%29%0Aresult1%20%3D%20sorted%28numbers%29%0Aresult2%20%3D%20sorted%28memoryless%29&cumulative=false&curInstr=4&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false))."
"The argument may already be materialized, as is the case with `numbers`, but may also be an *iterable* without any objects in it, such as `memoryless`. In both cases, we end up with materialized `list` objects with the elements sorted in *forward* order (cf., [PythonTutor](http://www.pythontutor.com/visualize.html#code=numbers%20%3D%20%5B7,%2011,%208,%205,%203,%2012,%202,%206,%209,%2010,%201,%204%5D%0Amemoryless%20%3D%20range%281,%2013%29%0Aresult1%20%3D%20sorted%28numbers%29%0Aresult2%20%3D%20sorted%28memoryless%29&cumulative=false&curInstr=4&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false))."
]
},
{
@ -11693,7 +11692,7 @@
{
"data": {
"text/plain": [
"<list_reverseiterator at 0x7f790c3339e8>"
"<list_reverseiterator at 0x7fb574372e90>"
]
},
"execution_count": 397,
@ -11717,7 +11716,7 @@
{
"data": {
"text/plain": [
"<range_iterator at 0x7f790c380780>"
"<range_iterator at 0x7fb574347540>"
]
},
"execution_count": 398,
@ -12216,7 +12215,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.7.4"
},
"livereveal": {
"auto_select": "code",
@ -12244,5 +12243,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View file

@ -0,0 +1,397 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Chapter 7: Sequential Data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Content Review"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb) of the book. Then, work through the questions below."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Essay Questions "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions *briefly*!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1**: We have seen **containers** and **iterables** before in [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb#Containers-vs.-Iterables). How do they relate to **sequences**? "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q2**: What are **abstract base classes**? How can we make use of the ones from the [collections.abc](https://docs.python.org/3/library/collections.abc.html) module in the [standard library](https://docs.python.org/3/library/index.html)?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3**: How are the *abstract behaviors* of **reversibility** and **finiteness** essential for *indexing* and *slicing* sequences?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q4**: Explain the difference between **mutable** and **immutable** objects in Python with the examples of the `list` and `tuple` types!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q5**: What is the difference between a **shallow** and a **deep** copy of an object? How can one of them become a \"problem?\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q6**: Many **list methods** change `list` objects \"**in place**.\" What do we mean by that?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7.1**: `tuple` objects have *two* primary usages. First, they can be used in place of `list` objects where **mutability** is *not* required. Second, we use them to model data **records**.\n",
"\n",
"Describe why `tuple` objects are a suitable replacement for `list` objects in general!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7.2**: What do we mean by a **record**? How are `tuple` objects suitable to model records? How can we integrate a **semantic meaning** when working with records into our code?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q8**: How is (iterable) **packing** and **unpacking** useful in the context of **function definitions** and **calls**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9**: With the [map()](https://docs.python.org/3/library/functions.html#map) and [filter()](https://docs.python.org/3/library/functions.html#filter) built-ins and the [reduce()](https://docs.python.org/3/library/functools.html#functools.reduce) function from the [functools](https://docs.python.org/3/library/functools.html) module in the [standard library](https://docs.python.org/3/library/index.html), we can replace many tedious `for`-loops and `if` statements. What are some advantages of doing so?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q10**: Looking at the `lambda` expression inside [reduce()](https://docs.python.org/3/library/functools.html#functools.reduce) below, what \"simple\" [built-in function](https://docs.python.org/3/library/functions.html) is mimicked here?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```python\n",
"from functools import reduce\n",
"\n",
"numbers = [7, 11, 8, 5, 3, 12, 2, 6, 9, 10, 1, 4]\n",
"\n",
"reduce(lambda x, y: x if x > y else y, numbers)\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11**: What is the primary use case of **list comprehensions**? Why do we describe them as **eager**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q12**: **Generator expressions** may replace `list` objects and list comprehensions in many scenarios. When evaluated, they create a **lazy** `generator` object that does *not* **materialize** its elements right away. What do we mean by that? What does it mean for a `generator` object to be **exhausted**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13**: What does it mean for the **boolean reducers**, the built-in [all()](https://docs.python.org/3/library/functions.html#all) and [any()](https://docs.python.org/3/library/functions.html#any) functions, to follow the **short-circuiting** strategy?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q14**: What is an **iterator**? How does it relate to an **iterable**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### True / False Questions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Motivate your answer with *one short* sentence!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15**: `sequence` objects are *not* part of core Python but may be imported from the [standard library](https://docs.python.org/3/library/index.html)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q16**: The built-in [sort()](https://docs.python.org/3/library/stdtypes.html#list.sort) function takes a *finite* **iterable** as its argument an returns a *new* `list` object. On the contrary, the [sorted()](https://docs.python.org/3/library/functions.html#sorted) method on `list` objects *mutates* them *in place*."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q17**: Passing **mutable** objects as arguments to functions is not problematic because functions operate in a **local** scope without affecting the **global** scope."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q18**: `lambda` expressions are useful in the context of the **map-filter-reduce** paradigm, where we often do *not* re-use a `function` object more than once."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q19**: Using **generator expressions** in place of **list comprehensions** wherever possible is a good practice as it makes our programs use memory more efficiently."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q20**: Just as **list comprehensions** create `list` objects, **tuple comprehensions** create `tuple` objects."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View file

@ -8,357 +8,6 @@
"# Chapter 7: Sequential Data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Content Review"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences.ipynb) of the book. Then work through the twenty review questions."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Essay Questions "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions briefly with *at most* 300 characters per question!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1**: We have seen **containers** and **iterables** before in [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb#Containers-vs.-Iterables). How do they relate to **sequences**? "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q2**: What are **abstract base classes**? How can we make use of the ones from the [collections.abc](https://docs.python.org/3/library/collections.abc.html) module in the [standard library](https://docs.python.org/3/library/index.html)?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3**: How are the *abstract behaviors* of **reversibility** and **finiteness** essential for *indexing* and *slicing* sequences?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q4**: Explain the difference between **mutable** and **immutable** objects in Python with the examples of the `list` and `tuple` types!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q5**: What is the difference between a **shallow** and a **deep** copy of an object? How can one of them become a \"problem?\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q6**: Many **list methods** change `list` objects \"**in place**.\" What do we mean by that?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7.1**: `tuple` objects have *two* primary usages. First, they can be used in place of `list` objects where **mutability** is *not* required. Second, we use them to model data **records**.\n",
"\n",
"Describe why `tuple` objects are a suitable replacement for `list` objects in general!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7.2**: What do we mean by a **record**? How are `tuple` objects suitable to model records? How can we integrate a **semantic meaning** when working with records into our code?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q8**: How is (iterable) **packing** and **unpacking** useful in the context of **function definitions** and **calls**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9**: With the [map()](https://docs.python.org/3/library/functions.html#map) and [filter()](https://docs.python.org/3/library/functions.html#filter) built-ins and the [reduce()](https://docs.python.org/3/library/functools.html#functools.reduce) function from the [functools](https://docs.python.org/3/library/functools.html) module in the [standard library](https://docs.python.org/3/library/index.html), we can replace many tedious `for`-loops and `if` statements. What are some advantages of doing so?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q10**: Looking at the `lambda` expression inside [reduce()](https://docs.python.org/3/library/functools.html#functools.reduce) below, what \"simple\" [built-in function](https://docs.python.org/3/library/functions.html) is mimicked here?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```python\n",
"from functools import reduce\n",
"\n",
"numbers = [7, 11, 8, 5, 3, 12, 2, 6, 9, 10, 1, 4]\n",
"\n",
"reduce(lambda x, y: x if x > y else y, numbers)\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11**: What is the primary use case of **list comprehensions**? Why do we describe them as **eager**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q12**: **Generator expressions** may replace `list` objects and list comprehensions in many scenarios. When evaluated, they create a **lazy** `generator` object that does *not* **materialize** its elements right away. What do we mean by that? What does it mean for a `generator` object to be **exhausted**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13**: What does it mean for the **boolean reducers**, the built-in [all()](https://docs.python.org/3/library/functions.html#all) and [any()](https://docs.python.org/3/library/functions.html#any) functions, to follow the **short-circuiting** strategy?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q14**: What is an **iterator**? How does it relate to an **iterable**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### True / False Questions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Motivate your answer with *one short* sentence!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q15**: `sequence` objects are *not* part of core Python but may be imported from the [standard library](https://docs.python.org/3/library/index.html)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q16**: The built-in [sort()](https://docs.python.org/3/library/stdtypes.html#list.sort) function takes a *finite* **iterable** as its argument an returns a *new* `list` object. On the contrary, the [sorted()](https://docs.python.org/3/library/functions.html#sorted) method on `list` objects *mutates* them *in place*."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q17**: Passing **mutable** objects as arguments to functions is not problematic because functions operate in a **local** scope without affecting the **global** scope."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q18**: `lambda` expressions are useful in the context of the **map-filter-reduce** paradigm, where we often do *not* re-use a `function` object more than once."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q19**: Using **generator expressions** in place of **list comprehensions** wherever possible is a good practice as it makes our programs use memory more efficiently."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q20**: Just as **list comprehensions** create `list` objects, **tuple comprehensions** create `tuple` objects."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -366,6 +15,13 @@
"## Coding Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb) of the book. Then, work through the exercises below."
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -377,7 +33,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q21.1**: Write a function `nested_sum()` that takes a `list` object as its argument, which contains other `list` objects with numbers, and adds up the numbers! Use `nested_numbers` below to test your function!\n",
"**Q1.1**: Write a function `nested_sum()` that takes a `list` object as its argument, which contains other `list` objects with numbers, and adds up the numbers! Use `nested_numbers` below to test your function!\n",
"\n",
"Hint: You need at least one `for`-loop."
]
@ -414,7 +70,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q21.2**: Provide a one-line expression to obtain the *same* result as `nested_sum()`!\n",
"**Q1.2**: Provide a one-line expression to obtain the *same* result as `nested_sum()`!\n",
"\n",
"Hints: Use a *list comprehension*, or maybe even a *generator expression*. You may want to use the built-in [sum()](https://docs.python.org/3/library/functions.html#sum) function several times."
]
@ -432,9 +88,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q21.3**: Generalize `nested_sum()` into a function `mixed_sum()` that can process a \"mixed\" `list` object, which contains numbers and other `list` objects with numbers! Use `mixed_numbers` below for testing!\n",
"**Q1.3**: Generalize `nested_sum()` into a function `mixed_sum()` that can process a \"mixed\" `list` object, which contains numbers and other `list` objects with numbers! Use `mixed_numbers` below for testing!\n",
"\n",
"Hints: Use the built-in [isinstance()](https://docs.python.org/3/library/functions.html#isinstance) function to check how an element is to be processed. Get extra credit for adhering to *goose typing*, as explained in [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers.ipynb#Goose-Typing)."
"Hints: Use the built-in [isinstance()](https://docs.python.org/3/library/functions.html#isinstance) function to check how an element is to be processed. Get extra credit for adhering to *goose typing*, as explained in [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers_00_content.ipynb#Goose-Typing)."
]
},
{
@ -478,7 +134,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q21.4.1**: Write a function `cum_sum()` that takes a `list` object with numbers as its argument and returns a *new* `list` object with the **cumulative sums** of these numbers! So, `sum_up` below, `[1, 2, 3, 4, 5]`, should return `[1, 3, 6, 10, 15]`.\n",
"**Q1.4.1**: Write a function `cum_sum()` that takes a `list` object with numbers as its argument and returns a *new* `list` object with the **cumulative sums** of these numbers! So, `sum_up` below, `[1, 2, 3, 4, 5]`, should return `[1, 3, 6, 10, 15]`.\n",
"\n",
"Hint: The idea behind is similar to the [cumulative distribution function](https://en.wikipedia.org/wiki/Cumulative_distribution_function) from statistics."
]
@ -515,7 +171,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q21.4.2**: We should always make sure that our functions also work in corner cases. What happens if your implementation of `cum_sum()` is called with an empty list `[]`? Make sure it handles that case *without* crashing! What would be a good return value in this corner case? Describe everything in the docstring.\n",
"**Q1.4.2**: We should always make sure that our functions also work in corner cases. What happens if your implementation of `cum_sum()` is called with an empty list `[]`? Make sure it handles that case *without* crashing! What would be a good return value in this corner case? Describe everything in the docstring.\n",
"\n",
"Hint: It is possible to write this without any extra input validation."
]
@ -540,7 +196,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"In the \"*Function Definitions & Calls*\" section in [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences.ipynb#Function-Definitions-&-Calls), we define the following function `product()`. In this exercise, you will improve it by making it more \"user-friendly.\""
"In the \"*Function Definitions & Calls*\" section in [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb#Function-Definitions-&-Calls), we define the following function `product()`. In this exercise, you will improve it by making it more \"user-friendly.\""
]
},
{
@ -565,7 +221,7 @@
"source": [
"The `*` in the function's header line *packs* all *positional* arguments passed to `product()` into one *iterable* called `args`.\n",
"\n",
"**Q22.1**: What is the data type of `args` within the function's body?"
"**Q2.1**: What is the data type of `args` within the function's body?"
]
},
{
@ -620,7 +276,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q22.2**: What line in the body of `product()` causes this exception? What is the exact problem?"
"**Q2.2**: What line in the body of `product()` causes this exception? What is the exact problem?"
]
},
{
@ -634,7 +290,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"In [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences.ipynb#Function-Definitions-&-Calls), we also pass a `list` object, like `one_hundred`, to `product()`, and *no* exception is raised."
"In [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb#Function-Definitions-&-Calls), we also pass a `list` object, like `one_hundred`, to `product()`, and *no* exception is raised."
]
},
{
@ -659,7 +315,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q22.3**: What is wrong with that? What *kind* of error (cf., [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb#Formal-vs.-Natural-Languages)) is that conceptually? Describe precisely what happens to the passed in `one_hundred` in every line within `product()`!"
"**Q2.3**: What is wrong with that? What *kind* of error (cf., [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_content.ipynb#Formal-vs.-Natural-Languages)) is that conceptually? Describe precisely what happens to the passed in `one_hundred` in every line within `product()`!"
]
},
{
@ -723,7 +379,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q22.4**: Describe why no error occurs by going over every line in `product()`!"
"**Q2.4**: Describe why no error occurs by going over every line in `product()`!"
]
},
{
@ -762,7 +418,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q22.5**: What line causes troubles now? What is the exact problem?"
"**Q2.5**: What line causes troubles now? What is the exact problem?"
]
},
{
@ -776,7 +432,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q22.6**: Replace the `None` in `product()` above with something reasonable that does *not* cause exceptions! Ensure that `product(42)` and `product(2, 5, 10)` return a correct result.\n",
"**Q2.6**: Replace the `None` in `product()` above with something reasonable that does *not* cause exceptions! Ensure that `product(42)` and `product(2, 5, 10)` return a correct result.\n",
"\n",
"Hints: It is ok if `product()` returns a result *different* from the `None` above. Look at the documentation of the built-in [sum()](https://docs.python.org/3/library/functions.html#sum) function for some inspiration."
]
@ -835,9 +491,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q22.7**: Rewrite `product()` so that it takes a *keyword-only* argument `start`, defaulting to the above *default* or *start* value, and use `start` internally instead of `result`!\n",
"**Q2.7**: Rewrite `product()` so that it takes a *keyword-only* argument `start`, defaulting to the above *default* or *start* value, and use `start` internally instead of `result`!\n",
"\n",
"Hint: Remember that a *keyword-only* argument is any parameter specified in a function's header line after the first (and only) `*` (cf., [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb#Keyword-only-Arguments))."
"Hint: Remember that a *keyword-only* argument is any parameter specified in a function's header line after the first (and only) `*` (cf., [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_00_content.ipynb#Keyword-only-Arguments))."
]
},
{
@ -946,7 +602,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q22.8**: What is a **collection**? How is that different from a **sequence**?"
"**Q2.8**: What is a **collection**? How is that different from a **sequence**?"
]
},
{
@ -960,7 +616,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q22.9**: Rewrite the latest version of `product()` to check if the *only* positional argument is a *collection* type! If so, its elements are multiplied together. Otherwise, the logic remains the same.\n",
"**Q2.9**: Rewrite the latest version of `product()` to check if the *only* positional argument is a *collection* type! If so, its elements are multiplied together. Otherwise, the logic remains the same.\n",
"\n",
"Hints: Use the built-in [len()](https://docs.python.org/3/library/functions.html#len) and [isinstance()](https://docs.python.org/3/library/functions.html#isinstance) functions to check if there is only *one* positional argument and if it is a *collection* type. Use the *abstract base class* `Collection` from the [collections.abc](https://docs.python.org/3/library/collections.abc.html) module in the [standard library](https://docs.python.org/3/library/index.html). You may want to *re-assign* `args` inside the body."
]
@ -1041,7 +697,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Side Note**: Above, we make `product()` work with a single *collection* type argument instead of a *sequence* type to keep it more generic: For example, we can pass in a `set` object, like `{2, 5, 10}` below, and `product()` continues to work correctly. The `set` type is introducted in [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings.ipynb#The-set-Type), and one essential difference to the `list` type is that objects of type `set` have *no* order regarding their elements. So, even though `[2, 5, 10]` and `{2, 5, 10}` look almost the same, the order implied in the literal notation gets lost in memory!"
"**Side Note**: Above, we make `product()` work with a single *collection* type argument instead of a *sequence* type to keep it more generic: For example, we can pass in a `set` object, like `{2, 5, 10}` below, and `product()` continues to work correctly. The `set` type is introducted in [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings_00_content.ipynb#The-set-Type), and one essential difference to the `list` type is that objects of type `set` have *no* order regarding their elements. So, even though `[2, 5, 10]` and `{2, 5, 10}` look almost the same, the order implied in the literal notation gets lost in memory!"
]
},
{
@ -1091,7 +747,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q22.10**: Adapt the latest version of `product()` to also raise a `TypeError` if called *without* any *positional* arguments!"
"**Q2.10**: Adapt the latest version of `product()` to also raise a `TypeError` if called *without* any *positional* arguments!"
]
},
{
@ -1279,7 +935,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q22.11**: What line causes the `TypeError`? What line is really the problem in the latest implementation of `product()`? Describe what happens on each line in the function's body until the exception is raised!"
"**Q2.11**: What line causes the `TypeError`? What line is really the problem in the latest implementation of `product()`? Describe what happens on each line in the function's body until the exception is raised!"
]
},
{
@ -1293,7 +949,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q22.12**: Adapt `product()` one last time to make it work with *iterators* as well!\n",
"**Q2.12**: Adapt `product()` one last time to make it work with *iterators* as well!\n",
"\n",
"Hints: This task is as easy as replacing `Collection` with something else. Which of the three behaviors of *collections* do *iterators* also exhibit? You may want to look at the documentations on the built-in [max()](https://docs.python.org/3/library/functions.html#max), [min()](https://docs.python.org/3/library/functions.html#min), and [sum()](https://docs.python.org/3/library/functions.html#sum) functions: What kind of argument do they take?"
]
@ -1442,7 +1098,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.1**: `list` objects are **sequences**. What *four* behaviors do they always come with?"
"**Q3.1**: `list` objects are **sequences**. What *four* behaviors do they always come with?"
]
},
{
@ -1456,7 +1112,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.2**: Write a function `mean()` that calculates the simple arithmetic mean of a given `sequence` with numbers!\n",
"**Q3.2**: Write a function `mean()` that calculates the simple arithmetic mean of a given `sequence` with numbers!\n",
"\n",
"Hints: You can solve this task with [built-in functions](https://docs.python.org/3/library/functions.html) only. A `for`-loop is *not* needed."
]
@ -1493,7 +1149,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.3**: Write a function `std()` that calculates the [standard deviation](https://en.wikipedia.org/wiki/Standard_deviation) of a `sequence` of numbers! Integrate your `mean()` version from before and the [sqrt()](https://docs.python.org/3/library/math.html#math.sqrt) function from the [math](https://docs.python.org/3/library/math.html) module in the [standard library](https://docs.python.org/3/library/index.html) provided to you below. Make sure `std()` calls `mean()` only *once* internally! Repeated calls to `mean()` would be a waste of computational resources.\n",
"**Q3.3**: Write a function `std()` that calculates the [standard deviation](https://en.wikipedia.org/wiki/Standard_deviation) of a `sequence` of numbers! Integrate your `mean()` version from before and the [sqrt()](https://docs.python.org/3/library/math.html#math.sqrt) function from the [math](https://docs.python.org/3/library/math.html) module in the [standard library](https://docs.python.org/3/library/index.html) provided to you below. Make sure `std()` calls `mean()` only *once* internally! Repeated calls to `mean()` would be a waste of computational resources.\n",
"\n",
"Hints: Parts of the code are probably too long to fit within the suggested 79 characters per line. So, use *temporary variables* inside your function. Instead of a `for`-loop, you may want to use a *list comprehension* or, even better, a memoryless *generator expression*."
]
@ -1539,7 +1195,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.4**: Complete `standardize()` below that takes a `sequence` of numbers and returns a `list` object with the **[z-scores](https://en.wikipedia.org/wiki/Standard_score)** of these numbers! A z-score is calculated by subtracting the mean and dividing by the standard deviation. Re-use `mean()` and `std()` from before. Again, ensure that `standardize()` calls `mean()` and `std()` only *once*! Further, round all z-scores with the built-in [round()](https://docs.python.org/3/library/functions.html#round) function and pass on the keyword-only argument `digits` to it.\n",
"**Q3.4**: Complete `standardize()` below that takes a `sequence` of numbers and returns a `list` object with the **[z-scores](https://en.wikipedia.org/wiki/Standard_score)** of these numbers! A z-score is calculated by subtracting the mean and dividing by the standard deviation. Re-use `mean()` and `std()` from before. Again, ensure that `standardize()` calls `mean()` and `std()` only *once*! Further, round all z-scores with the built-in [round()](https://docs.python.org/3/library/functions.html#round) function and pass on the keyword-only argument `digits` to it.\n",
"\n",
"Hint: You may want to use a *list comprehension* instead of a `for`-loop."
]
@ -1610,7 +1266,7 @@
"source": [
"Even though `standardize()` calls `mean()` and `std()` only once each, `mean()` is called *twice*! That is so because `std()` internally also re-uses `mean()`!\n",
"\n",
"**Q23.5.1**: Rewrite `std()` to take an optional keyword-only argument `seq_mean`, defaulting to `None`. If provided, `seq_mean` is used instead of the result of calling `mean()`. Otherwise, the latter is called.\n",
"**Q3.5.1**: Rewrite `std()` to take an optional keyword-only argument `seq_mean`, defaulting to `None`. If provided, `seq_mean` is used instead of the result of calling `mean()`. Otherwise, the latter is called.\n",
"\n",
"Hint: You must check if `seq_mean` is still the default value."
]
@ -1654,7 +1310,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.5.2**: Now, rewrite `standardize()` to pass on the return value of `mean()` to `std()`! In summary, `standardize()` calculates the z-scores for the numbers in the `sequence` with as few computational steps as possible."
"**Q3.5.2**: Now, rewrite `standardize()` to pass on the return value of `mean()` to `std()`! In summary, `standardize()` calculates the z-scores for the numbers in the `sequence` with as few computational steps as possible."
]
},
{
@ -1689,7 +1345,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.6**: With both `sample` and `z_scores` being materialized `list` objects, we can loop over pairs consisting of a number from `sample` and its corresponding z-score. Write a `for`-loop that prints out all the \"outliers,\" as which we define numbers with an absolute z-score above `1.96`. There are *four* of them in the `sample`.\n",
"**Q3.6**: With both `sample` and `z_scores` being materialized `list` objects, we can loop over pairs consisting of a number from `sample` and its corresponding z-score. Write a `for`-loop that prints out all the \"outliers,\" as which we define numbers with an absolute z-score above `1.96`. There are *four* of them in the `sample`.\n",
"\n",
"Hint: Use the [abs()](https://docs.python.org/3/library/functions.html#abs) and [zip()](https://docs.python.org/3/library/functions.html#zip) built-ins."
]
@ -1798,7 +1454,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.7**: What happens if you call `mean()` with `data` as the argument? What is the problem?\n",
"**Q3.7**: What happens if you call `mean()` with `data` as the argument? What is the problem?\n",
"\n",
"Hints: If you try it out, you may have to press the \"Stop\" button in the toolbar at the top. Your computer should *not* crash, but you will *have to* restart this Jupyter notebook with \"Kernel\" > \"Restart\" and import `data` again."
]
@ -1823,7 +1479,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.8**: Write a function `take_sample()` that takes an `iterator` as its argument, like `data`, and creates a *materialized* `list` object out of its first `n` elements, defaulting to `1_000`!\n",
"**Q3.8**: Write a function `take_sample()` that takes an `iterator` as its argument, like `data`, and creates a *materialized* `list` object out of its first `n` elements, defaulting to `1_000`!\n",
"\n",
"Hints: [next()](https://docs.python.org/3/library/functions.html#next) and the [range()](https://docs.python.org/3/library/functions.html#func-range) built-in may be helpful. You may want to use a *list comprehension* instead of a `for`-loop and write a one-liner. Audacious students may want to look at [isclice()](https://docs.python.org/3/library/itertools.html#itertools.islice) in the [itertools](https://docs.python.org/3/library/itertools.html) module in the [standard library](https://docs.python.org/3/library/index.html)."
]
@ -1885,7 +1541,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.9**: Convert `standardize()` into a *new* function `standardized()` that implements the *same* logic but works on a possibly *infinite* stream of data, provided as an `iterable`, instead of a *finite* `sequence`.\n",
"**Q3.9**: Convert `standardize()` into a *new* function `standardized()` that implements the *same* logic but works on a possibly *infinite* stream of data, provided as an `iterable`, instead of a *finite* `sequence`.\n",
"\n",
"To calculate a z-score, we need the stream's overall mean and standard deviation, and that is *impossible* to calculate if we do not know how long the stream is, and, in particular, if it is *infinite*. So, `standardized()` first takes a sample from the `iterable` internally, and uses the sample's mean and standard deviation to calculate the z-scores.\n",
"\n",
@ -1949,7 +1605,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.10.1**: `standardized()` allows us to go over an *infinite* stream of z-scores. What we want to do instead is to loop over the stream's raw numbers and skip the outliers. In the remainder of this exercise, you look at the parts that make up the `skip_outliers()` function below to achieve precisely that.\n",
"**Q3.10.1**: `standardized()` allows us to go over an *infinite* stream of z-scores. What we want to do instead is to loop over the stream's raw numbers and skip the outliers. In the remainder of this exercise, you look at the parts that make up the `skip_outliers()` function below to achieve precisely that.\n",
"\n",
"The first steps in `skip_outliers()` are the same as in `standardized()`: We take a `sample` from the stream of `data` and calculate its statistics."
]
@ -1969,9 +1625,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.10.2**: Just as in `standardized()`, write a *generator expression* that produces z-scores one by one! However, instead of just generating a z-score, the resulting `generator` object should produce `tuple` objects consisting of a \"raw\" number from `data` and its z-score.\n",
"**Q3.10.2**: Just as in `standardized()`, write a *generator expression* that produces z-scores one by one! However, instead of just generating a z-score, the resulting `generator` object should produce `tuple` objects consisting of a \"raw\" number from `data` and its z-score.\n",
"\n",
"Hint: Look at the revisited \"*Averaging Even Numbers*\" example in [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences.ipynb#Example:-Averaging-Even-Numbers-%28revisited%29) for some inspiration, which also contains a generator expression producing `tuple` objects."
"Hint: Look at the revisited \"*Averaging Even Numbers*\" example in [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb#Example:-Averaging-Even-Numbers-%28revisited%29) for some inspiration, which also contains a generator expression producing `tuple` objects."
]
},
{
@ -2003,7 +1659,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.10.3**: Write another generator expression that loops over `standardizer`. It contains an `if`-clause that keeps only numbers with an absolute z-score below the `threshold_z`. If you fancy, use *tuple unpacking*."
"**Q3.10.3**: Write another generator expression that loops over `standardizer`. It contains an `if`-clause that keeps only numbers with an absolute z-score below the `threshold_z`. If you fancy, use *tuple unpacking*."
]
},
{
@ -2044,7 +1700,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.10.4**: Lastly, put everything together in the `skip_outliers()` function! Make sure you refer to `iterable` inside the function and not the global `data`."
"**Q3.10.4**: Lastly, put everything together in the `skip_outliers()` function! Make sure you refer to `iterable` inside the function and not the global `data`."
]
},
{
@ -2109,7 +1765,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q23.11**: You implemented the functions `mean()`, `std()`, `standardize()`, `standardized()`, and `skip_outliers()`. Which of them are **eager**, and which are **lazy**? How do these two concepts relate to **finite** and **infinite** data?"
"**Q3.11**: You implemented the functions `mean()`, `std()`, `standardize()`, `standardized()`, and `skip_outliers()`. Which of them are **eager**, and which are **lazy**? How do these two concepts relate to **finite** and **infinite** data?"
]
},
{
@ -2136,7 +1792,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
@ -2153,5 +1809,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View file

@ -19,9 +19,9 @@
}
},
"source": [
"While [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences.ipynb) focuses on one special kind of *collection* types, namely *sequences*, this chapter introduces two more: **Mappings** and **sets**. We present the data types belonging to these two groups in one chapter as they share the *same* underlying implementation at the C Level, known as **[hash tables](https://en.wikipedia.org/wiki/Hash_table)**.\n",
"While [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb) focuses on one special kind of *collection* types, namely *sequences*, this chapter introduces two more kinds: **Mappings** and **sets**. We present the data types belonging to these two groups in one chapter as they share the *same* underlying implementation at the C Level, known as **[hash tables](https://en.wikipedia.org/wiki/Hash_table)**.\n",
"\n",
"The most important mapping type in this chapter is the `dict` type that we have not yet seen before (cf, [documentation](https://docs.python.org/3/library/stdtypes.html#dict)). It is an essential part in a data science practitioner's toolbox for two reasons: First, Python employs `dict` objects basically \"everywhere\" internally. So, we must understand how they work to become better at Python in general. Second, after the many concepts related to *sequential* data, the ideas behind *mappings* enhance our general problem solving skills. As a concrete example, we look at the concept of **memoization** to complete our picture of *recursion*, as depicted in [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb#Recursion). We end this chapter with a discussion of *set* types."
"The most important mapping type in this chapter is the `dict` type that we have not yet seen before (cf, [documentation](https://docs.python.org/3/library/stdtypes.html#dict)). It is an essential part in a data science practitioner's toolbox for two reasons: First, Python employs `dict` objects basically \"everywhere\" internally. So, we must understand how they work to become better at Python in general. Second, after the many concepts related to *sequential* data, the ideas behind *mappings* enhance our general problem solving skills. As a concrete example, we look at the concept of **memoization** to complete our picture of *recursion*, as depicted in [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb#Recursion). We end this chapter with a discussion of *set* types."
]
},
{
@ -45,7 +45,7 @@
"source": [
"A *mapping* is a one-to-one correspondence from a set of **keys** to a set of **values**. In other words, a *mapping* is a *collection* of **key-value pairs**, also called **items** for short.\n",
"\n",
"In the context of mappings, the term *value* has a meaning different from the general *value* that *every* object has: In the \"bag\" analogy from [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb#Value), we descibe an object's value to be the concrete $0$s and $1$s it contains. Here, the terms *key* and *value* mean the *role* an object takes within a mapping. Both, *keys* and *values*, are real *objects* with a distinct *value*. So, the student should always remember the double meaning of the term *value* in this chapter!\n",
"In the context of mappings, the term *value* has a meaning different from the general *value* that *every* object has: In the \"bag\" analogy from [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_content.ipynb#Value), we descibe an object's value to be the concrete $0$s and $1$s it contains. Here, the terms *key* and *value* mean the *role* an object takes within a mapping. Both, *keys* and *values*, are real *objects* with a distinct *value*. So, the student should always remember the double meaning of the term *value* in this chapter!\n",
"\n",
"Let's continue with an example. To create a `dict` object, we commonly use the literal notation, `{..: .., ..: .., ...}`, and list all the items. `to_words` below maps the `int` objects `0`, `1`, and `2` to their English word equivalents, `\"zero\"`, `\"one\"`, and `\"two\"`, and `from_words` does the opposite. A stylistic side note: Pythonistas often expand `dict` or `list` definitions by writing each item or element on a line on their own. The commas `,` after the *last* items are *not* a mistake, as well, although they *may* be left out. Besides easier reading, such style has actual technical advantages (cf., [source](https://www.python.org/dev/peps/pep-0008/#when-to-use-trailing-commas)) that we do not go into detail about here."
]
@ -107,7 +107,7 @@
{
"data": {
"text/plain": [
"139752734794304"
"139953979690352"
]
},
"execution_count": 3,
@ -502,7 +502,7 @@
}
},
"source": [
"In [Chapter 0](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/00_start_up.ipynb#Isn't-C-a-lot-faster?), we argue that a major advantage of using Python is that it takes care of the memory managment for us. In line with that, we have never talked about the C level implementation thus far in the book. However, the `dict` type, among others, exhibits some behaviors that may seem \"weird\" for a beginner. To built a solid intuition that enables the student to better \"predict\" how `dict` objects behave, we describe the underlying implementation details on a conceptual level (i.e., without C code).\n",
"In [Chapter 0](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/00_start_up_00_content.ipynb#Isn't-C-a-lot-faster?), we argue that a major advantage of using Python is that it takes care of the memory managment for us. In line with that, we have never talked about the C level implementation thus far in the book. However, the `dict` type, among others, exhibits some behaviors that may seem \"weird\" for a beginner. To built a solid intuition that enables the student to better \"predict\" how `dict` objects behave, we describe the underlying implementation details on a conceptual level (i.e., without C code).\n",
"\n",
"The first unintuitive behavior is that we may *not* use a *mutable* object as a key. That results in a `TypeError`."
]
@ -597,10 +597,10 @@
}
},
"source": [
"| Bucket | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |\n",
"| :---: |:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|\n",
"| Key |*...*|*...*|*...*|*...*|*...*|*...*|*...*|*...*|\n",
"| Value |*...*|*...*|*...*|*...*|*...*|*...*|*...*|*...*|"
"| Bucket | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |\n",
"| :---: |:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|\n",
"| **Key** |*...*|*...*|*...*|*...*|*...*|*...*|*...*|*...*|\n",
"|**Value**|*...*|*...*|*...*|*...*|*...*|*...*|*...*|*...*|"
]
},
{
@ -628,7 +628,7 @@
{
"data": {
"text/plain": [
"-2242252796476499076"
"-1033934764475250610"
]
},
"execution_count": 17,
@ -707,7 +707,7 @@
}
},
"source": [
"The [glossary](https://docs.python.org/3/glossary.html#term-hashable) states a second requirement for hashability, namely that \"objects which *compare equal* must have the *same* hash value.\" The purpose of this is to ensure that if we put, for example, `1` as a key in a `dict` object, we can look it up later with `1.0`. In other words, we can look up keys by their object's value (i.e., in the meaning of [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb#Value)). The converse statement does *not* hold: Two objects *may* (accidentally) have the *same* hash value and *not* compare equal."
"The [glossary](https://docs.python.org/3/glossary.html#term-hashable) states a second requirement for hashability, namely that \"objects which *compare equal* must have the *same* hash value.\" The purpose of this is to ensure that if we put, for example, `1` as a key in a `dict` object, we can look it up later with `1.0`. In other words, we can look up keys by their object's value (i.e., in the meaning of [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_content.ipynb#Value)). The converse statement does *not* hold: Two objects *may* (accidentally) have the *same* hash value and *not* compare equal."
]
},
{
@ -951,12 +951,12 @@
"name": "stdout",
"output_type": "stream",
"text": [
"zero\t-2242252796476499076\t0b...010010000100\t100\t4\n",
"one\t6742734203392562231\t0b...010000110111\t111\t7\n",
"two\t8400825950927958036\t0b...000000010100\t100\t4\n",
"three\t-7473701886709619306\t0b...101001101010\t010\t2\n",
"four\t5854090567539607813\t0b...100100000101\t101\t5\n",
"five\t5010767421024509913\t0b...111111011001\t001\t1\n"
"zero\t-1033934764475250610\t0b...011110110010\t010\t2\n",
"one\t-3496683303036773129\t0b...001100001001\t001\t1\n",
"two\t-4468022785493412346\t0b...100111111010\t010\t2\n",
"three\t1491334499222274950\t0b...001110000110\t110\t6\n",
"four\t490235692124377396\t0b...000100110100\t100\t4\n",
"five\t-550474145318920636\t0b...000110111100\t100\t4\n"
]
}
],
@ -983,10 +983,10 @@
}
},
"source": [
"| Bucket | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |\n",
"| :---: | :---: |:---:| :---: | :---: |:---:| :---: |:---:| :---: |\n",
"| Key |`\"one\"`|*...*|`\"two\"`|`\"four\"`|*...*|`\"three\"`|*...*|`\"zero\"`|\n",
"| Value | `1` |*...*| `2` | `4` |*...*| `3` |*...*| `0` |"
"| Bucket | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |\n",
"| :---: | :---: |:---:| :---: | :---: |:---:| :---: |:---:| :---: |\n",
"| **Key** |`\"one\"`|*...*|`\"two\"`|`\"four\"`|*...*|`\"three\"`|*...*|`\"zero\"`|\n",
"|**Value**| `1` |*...*| `2` | `4` |*...*| `3` |*...*| `0` |"
]
},
{
@ -1008,10 +1008,10 @@
}
},
"source": [
"| Bucket | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |\n",
"| :---: | :---: |:---:|:---:|:---:|:---:|:---:|:---:| :---: |:---:|:---:| :---: | :---: |:---:| :---: |:---:| :---: |\n",
"| Key |`\"one\"`|*...*|*...*|*...*|*...*|*...*|*...*|`\"five\"`|*...*|*...*|`\"two\"`|`\"four\"`|*...*|`\"three\"`|*...*|`\"zero\"`|\n",
"| Value | `1` |*...*|*...*|*...*|*...*|*...*|*...*| `5` |*...*|*...*| `2` | `4` |*...*| `3` |*...*| `0` |"
"| Bucket | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |\n",
"| :---: | :---: |:---:|:---:|:---:|:---:|:---:|:---:| :---: |:---:|:---:| :---: | :---: |:---:| :---: |:---:| :---: |\n",
"| **Key** |`\"one\"`|*...*|*...*|*...*|*...*|*...*|*...*|`\"five\"`|*...*|*...*|`\"two\"`|`\"four\"`|*...*|`\"three\"`|*...*|`\"zero\"`|\n",
"|**Value**| `1` |*...*|*...*|*...*|*...*|*...*|*...*| `5` |*...*|*...*| `2` | `4` |*...*| `3` |*...*| `0` |"
]
},
{
@ -1038,12 +1038,12 @@
"name": "stdout",
"output_type": "stream",
"text": [
"zero\t-2242252796476499076\t0b...010010000100\t0100\t4\n",
"one\t6742734203392562231\t0b...010000110111\t0111\t7\n",
"two\t8400825950927958036\t0b...000000010100\t0100\t4\n",
"three\t-7473701886709619306\t0b...101001101010\t1010\t10\n",
"four\t5854090567539607813\t0b...100100000101\t0101\t5\n",
"five\t5010767421024509913\t0b...111111011001\t1001\t9\n"
"zero\t-1033934764475250610\t0b...011110110010\t0010\t2\n",
"one\t-3496683303036773129\t0b...001100001001\t1001\t9\n",
"two\t-4468022785493412346\t0b...100111111010\t1010\t10\n",
"three\t1491334499222274950\t0b...001110000110\t0110\t6\n",
"four\t490235692124377396\t0b...000100110100\t0100\t4\n",
"five\t-550474145318920636\t0b...000110111100\t1100\t12\n"
]
}
],
@ -1070,7 +1070,7 @@
}
},
"source": [
"### Mappings are Collections without \"Predictable Order\""
"### Mappings are Collections without \"Predictable\" Order"
]
},
{
@ -1081,7 +1081,7 @@
}
},
"source": [
"In [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences.ipynb#Collections-vs.-Sequences), we show how *sequences* are a special kind of *collections*. The latter can be described as iterable containers with a finite number of elements.\n",
"In [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb#Collections-vs.-Sequences), we show how *sequences* are a special kind of *collections*. The latter can be described as iterable containers with a finite number of elements.\n",
"\n",
"The `dict` type is a special kind of a *collection*, as well, as revealed with the `Collection` ABC from the [collections.abc](https://docs.python.org/3/library/collections.abc.html) module in the [standard library](https://docs.python.org/3/library/index.html)."
]
@ -1291,12 +1291,12 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Python 3.7.3\r\n"
"Python 3.7.4\n"
]
}
],
"source": [
"!python --version # the order in the for-loops is predictable for Python 3.7 or higher only"
"!python --version # the order in the for-loops is predictable only for Python 3.7 or higher"
]
},
{
@ -1811,7 +1811,7 @@
},
"outputs": [],
"source": [
"haystack = [random.randint(99, 9999) for _ in range(10_000_000)] + [42]"
"needle = 42"
]
},
{
@ -1824,7 +1824,8 @@
},
"outputs": [],
"source": [
"needle = 42"
"haystack = [random.randint(99, 9999) for _ in range(10_000_000)]\n",
"haystack.append(needle)"
]
},
{
@ -1863,7 +1864,7 @@
{
"data": {
"text/plain": [
"[8126, 7370, 3735, 213, 7922, 1434, 8557, 9609, 9704, 9564, 9601, 3444]"
"[8126, 7370, 3735, 213, 7922, 1434, 8557, 9609, 9704, 9564]"
]
},
"execution_count": 57,
@ -1872,7 +1873,7 @@
}
],
"source": [
"haystack[:12]"
"haystack[:10]"
]
},
{
@ -1887,7 +1888,7 @@
{
"data": {
"text/plain": [
"[5842, 1894, 7237, 886, 5945, 4014, 4998, 2055, 3531, 6919, 7875, 1944]"
"[7237, 886, 5945, 4014, 4998, 2055, 3531, 6919, 7875, 1944]"
]
},
"execution_count": 58,
@ -1896,7 +1897,7 @@
}
],
"source": [
"haystack[-12:]"
"haystack[-10:]"
]
},
{
@ -1923,7 +1924,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"4.37 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
"4.32 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
]
}
],
@ -1965,7 +1966,7 @@
}
},
"source": [
"Because the hash table implementation is *extremely* fast, we search the `needle` not `10` but `10_000` times. The code cell still runs in only a fraction of the time its counterpart does above."
"To show the *massive* effect of the hash table implementation, we search the `needle` not `10` but `10_000_000` times. The code cell still runs in only a fraction of the time its counterpart does above."
]
},
{
@ -1981,7 +1982,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"426 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
"419 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
]
}
],
@ -2447,7 +2448,7 @@
{
"data": {
"text/plain": [
"139752734711240"
"139953979638320"
]
},
"execution_count": 75,
@ -2638,7 +2639,7 @@
}
},
"source": [
"`dict` objects come with many methods bound on them, many of which are standardized by the `Mapping` and `MutableMapping` ABCs from the [collections.abc](https://docs.python.org/3/library/collections.abc.html) module. While the former requires a data type adhering to it to implement the [keys()](https://docs.python.org/3/library/stdtypes.html#dict.keys), [values()](https://docs.python.org/3/library/stdtypes.html#dict.values), [items()](https://docs.python.org/3/library/stdtypes.html#dict.items), and [get()](https://docs.python.org/3/library/stdtypes.html#dict.get) methods, which *never* mutate an object, the latter formalizes the [update()](https://docs.python.org/3/library/stdtypes.html#dict.update), [pop()](https://docs.python.org/3/library/stdtypes.html#dict.pop), [popitem()](https://docs.python.org/3/library/stdtypes.html#dict.popitem), [clear()](https://docs.python.org/3/library/stdtypes.html#dict.clear), and [setdefault()](https://docs.python.org/3/library/stdtypes.html#dict.setdefault) methods, which *may* do so."
"`dict` objects come with many methods bound on them (cf., [documentation](https://docs.python.org/3/library/stdtypes.html#dict)), many of which are standardized by the `Mapping` and `MutableMapping` ABCs from the [collections.abc](https://docs.python.org/3/library/collections.abc.html) module. While the former requires a data type adhering to it to implement the [keys()](https://docs.python.org/3/library/stdtypes.html#dict.keys), [values()](https://docs.python.org/3/library/stdtypes.html#dict.values), [items()](https://docs.python.org/3/library/stdtypes.html#dict.items), and [get()](https://docs.python.org/3/library/stdtypes.html#dict.get) methods, which *never* mutate an object, the latter formalizes the [update()](https://docs.python.org/3/library/stdtypes.html#dict.update), [pop()](https://docs.python.org/3/library/stdtypes.html#dict.pop), [popitem()](https://docs.python.org/3/library/stdtypes.html#dict.popitem), [clear()](https://docs.python.org/3/library/stdtypes.html#dict.clear), and [setdefault()](https://docs.python.org/3/library/stdtypes.html#dict.setdefault) methods, which *may* do so."
]
},
{
@ -2929,7 +2930,7 @@
}
},
"source": [
"Above, we see how the look-up operator fails *loudly* if a key is not in a `dict` object. For example, `to_words` does *not* have a key `0` any more."
"Above, we see how the look-up operator fails *loudly* with a `KeyError` if a key is *not* in a `dict` object. For example, `to_words` does *not* have a key `0` any more."
]
},
{
@ -3768,7 +3769,7 @@
}
},
"source": [
"Just as a single `*` symbol is used for packing and unpacking iterables in [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences.ipynb#Packing-&-Unpacking), a double `**` symbol implements packing and unpacking for mappings.\n",
"Just as a single `*` symbol is used for packing and unpacking iterables in [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb#Packing-&-Unpacking), a double `**` symbol implements packing and unpacking for mappings.\n",
"\n",
"Let's say we have `to_words` and `more_words` as below and want to merge the items together into a *new* `dict` object."
]
@ -3815,7 +3816,7 @@
}
},
"source": [
"By *unpacking* the items with `**`, the newly created `dict` objects is first filled with the items from `to_words` and then from `more_words`. The item with the key `2` from `more_words` overwrites its counterpart from `to_words` as it is mentioned last."
"By *unpacking* the items with `**`, the newly created `dict` object is first filled with the items from `to_words` and then from `more_words`. The item with the key `2` from `more_words` overwrites its counterpart from `to_words` as it is mentioned last."
]
},
{
@ -4194,7 +4195,7 @@
}
},
"source": [
"Analogous to list comprehensions in [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences.ipynb#List-Comprehensions), **dictionary comprehensions**, or **dictcomps** for short, are a concise literal notation to derive new `dict` objects out of existing ones.\n",
"Analogous to list comprehensions in [Chapter 7](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb#List-Comprehensions), **dictionary comprehensions**, or **dictcomps** for short, are a concise literal notation to derive new `dict` objects out of existing ones.\n",
"\n",
"For example, let's derive `from_words` from `to_words` below by swapping the keys and values."
]
@ -4409,7 +4410,7 @@
}
},
"source": [
"The *recursive* implementation of the [Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number) in [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb#\"Easy-at-first-Glance\"-Example:-Fibonacci-Numbers) takes long to compute for large Fibonacci numbers as the number of function calls grows exponentially.\n",
"The *recursive* implementation of the [Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number) in [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb#\"Easy-at-first-Glance\"-Example:-Fibonacci-Numbers) takes long to compute for large Fibonacci numbers as the number of function calls grows exponentially.\n",
"\n",
"The graph below visualizes what the problem is and also suggests a solution: Instead of calculating the return value of the `fibonacci()` function for the *same* argument over and over again, it makes sense to **cache** the result and reuse it. This concept is called **[memoization](https://en.wikipedia.org/wiki/Memoization)** in the computer science literature."
]
@ -4563,7 +4564,7 @@
}
},
"source": [
"Now, calling `fibonacci()` has the *side effect* of growing the `memo` in the *global scope*. So, subsequent calls to `fibonacci()` need not calculate any Fibonacci number with an index `i` smaller than the maximum `i` used so far."
"Now, calling `fibonacci()` has the *side effect* of growing the `memo` in the *global scope*. So, subsequent calls to `fibonacci()` need not calculate any Fibonacci number with an index `i` smaller than the maximum `i` used so far. Because of that, this `fibonacci()` is *not* a *pure* function."
]
},
{
@ -4663,8 +4664,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"The slowest run took 195.30 times longer than the fastest. This could mean that an intermediate result is being cached.\n",
"18.9 µs ± 44.4 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
"The slowest run took 183.70 times longer than the fastest. This could mean that an intermediate result is being cached.\n",
"21.4 µs ± 50.4 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
]
}
],
@ -4686,8 +4687,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"The slowest run took 1919.60 times longer than the fastest. This could mean that an intermediate result is being cached.\n",
"346 µs ± 844 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
"The slowest run took 1974.48 times longer than the fastest. This could mean that an intermediate result is being cached.\n",
"580 µs ± 1.41 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
]
}
],
@ -4727,12 +4728,12 @@
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mRecursionError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-152-cc76051ea9de>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_cell_magic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'timeit'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'-n 1'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'fibonacci(9999) # = 10,000th number\\n'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m~/.pyenv/versions/anaconda3-2019.07/lib/python3.7/site-packages/IPython/core/interactiveshell.py\u001b[0m in \u001b[0;36mrun_cell_magic\u001b[0;34m(self, magic_name, line, cell)\u001b[0m\n\u001b[1;32m 2356\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuiltin_trap\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2357\u001b[0m \u001b[0margs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mmagic_arg_s\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2358\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2359\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 2360\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m</home/webartifex/.pyenv/versions/anaconda3-2019.07/lib/python3.7/site-packages/decorator.py:decorator-gen-60>\u001b[0m in \u001b[0;36mtimeit\u001b[0;34m(self, line, cell, local_ns)\u001b[0m\n",
"\u001b[0;32m~/.pyenv/versions/anaconda3-2019.07/lib/python3.7/site-packages/IPython/core/magic.py\u001b[0m in \u001b[0;36m<lambda>\u001b[0;34m(f, *a, **k)\u001b[0m\n\u001b[1;32m 185\u001b[0m \u001b[0;31m# but it's overkill for just that one bit of state.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 186\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmagic_deco\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\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[0;32m--> 187\u001b[0;31m \u001b[0mcall\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 188\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 189\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcallable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\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[0;32m~/.pyenv/versions/anaconda3-2019.07/lib/python3.7/site-packages/IPython/core/magics/execution.py\u001b[0m in \u001b[0;36mtimeit\u001b[0;34m(self, line, cell, local_ns)\u001b[0m\n\u001b[1;32m 1160\u001b[0m \u001b[0;32mbreak\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1161\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1162\u001b[0;31m \u001b[0mall_runs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtimer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrepeat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrepeat\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnumber\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1163\u001b[0m \u001b[0mbest\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mall_runs\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mnumber\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1164\u001b[0m \u001b[0mworst\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmax\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mall_runs\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mnumber\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/.pyenv/versions/anaconda3-2019.07/lib/python3.7/timeit.py\u001b[0m in \u001b[0;36mrepeat\u001b[0;34m(self, repeat, number)\u001b[0m\n\u001b[1;32m 202\u001b[0m \u001b[0mr\u001b[0m \u001b[0;34m=\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[1;32m 203\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrepeat\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[0;32m--> 204\u001b[0;31m \u001b[0mt\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtimeit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnumber\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 205\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 206\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/.pyenv/versions/anaconda3-2019.07/lib/python3.7/site-packages/IPython/core/magics/execution.py\u001b[0m in \u001b[0;36mtimeit\u001b[0;34m(self, number)\u001b[0m\n\u001b[1;32m 167\u001b[0m \u001b[0mgc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdisable\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[1;32m 168\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 169\u001b[0;31m \u001b[0mtiming\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minner\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mit\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtimer\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 170\u001b[0m \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 171\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mgcold\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/.pyenv/versions/anaconda3-2019.10/lib/python3.7/site-packages/IPython/core/interactiveshell.py\u001b[0m in \u001b[0;36mrun_cell_magic\u001b[0;34m(self, magic_name, line, cell)\u001b[0m\n\u001b[1;32m 2357\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuiltin_trap\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2358\u001b[0m \u001b[0margs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mmagic_arg_s\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2359\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2360\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 2361\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m</home/webartifex/.pyenv/versions/anaconda3-2019.10/lib/python3.7/site-packages/decorator.py:decorator-gen-60>\u001b[0m in \u001b[0;36mtimeit\u001b[0;34m(self, line, cell, local_ns)\u001b[0m\n",
"\u001b[0;32m~/.pyenv/versions/anaconda3-2019.10/lib/python3.7/site-packages/IPython/core/magic.py\u001b[0m in \u001b[0;36m<lambda>\u001b[0;34m(f, *a, **k)\u001b[0m\n\u001b[1;32m 185\u001b[0m \u001b[0;31m# but it's overkill for just that one bit of state.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 186\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmagic_deco\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\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[0;32m--> 187\u001b[0;31m \u001b[0mcall\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 188\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 189\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcallable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\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[0;32m~/.pyenv/versions/anaconda3-2019.10/lib/python3.7/site-packages/IPython/core/magics/execution.py\u001b[0m in \u001b[0;36mtimeit\u001b[0;34m(self, line, cell, local_ns)\u001b[0m\n\u001b[1;32m 1160\u001b[0m \u001b[0;32mbreak\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1161\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1162\u001b[0;31m \u001b[0mall_runs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtimer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrepeat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrepeat\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnumber\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1163\u001b[0m \u001b[0mbest\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mall_runs\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mnumber\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1164\u001b[0m \u001b[0mworst\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmax\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mall_runs\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mnumber\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/.pyenv/versions/anaconda3-2019.10/lib/python3.7/timeit.py\u001b[0m in \u001b[0;36mrepeat\u001b[0;34m(self, repeat, number)\u001b[0m\n\u001b[1;32m 202\u001b[0m \u001b[0mr\u001b[0m \u001b[0;34m=\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[1;32m 203\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrepeat\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[0;32m--> 204\u001b[0;31m \u001b[0mt\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtimeit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnumber\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 205\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 206\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/.pyenv/versions/anaconda3-2019.10/lib/python3.7/site-packages/IPython/core/magics/execution.py\u001b[0m in \u001b[0;36mtimeit\u001b[0;34m(self, number)\u001b[0m\n\u001b[1;32m 167\u001b[0m \u001b[0mgc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdisable\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[1;32m 168\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 169\u001b[0;31m \u001b[0mtiming\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minner\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mit\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtimer\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 170\u001b[0m \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 171\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mgcold\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m<magic-timeit>\u001b[0m in \u001b[0;36minner\u001b[0;34m(_it, _timer)\u001b[0m\n",
"\u001b[0;32m<ipython-input-146-223333299fa0>\u001b[0m in \u001b[0;36mfibonacci\u001b[0;34m(i, debug)\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"fibonacci({i}) is calculated\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 25\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 26\u001b[0;31m \u001b[0mrecurse\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfibonacci\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdebug\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdebug\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mfibonacci\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdebug\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdebug\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 27\u001b[0m \u001b[0mmemo\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrecurse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mrecurse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"... last 1 frames repeated, from the frame below ...\n",
@ -4844,8 +4845,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"The slowest run took 25077.61 times longer than the fastest. This could mean that an intermediate result is being cached.\n",
"2.36 ms ± 5.77 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
"The slowest run took 27724.52 times longer than the fastest. This could mean that an intermediate result is being cached.\n",
"3.11 ms ± 7.61 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
]
}
],
@ -4994,7 +4995,7 @@
}
},
"source": [
"Because `fibonacci()` is now independent from *global state*, the same eleven recursive function calls are made each time."
"Because `fibonacci()` is now independent from *global state*, the same eleven recursive function calls are made each time. So, this `fibonacci()` is a *pure* function."
]
},
{
@ -5073,7 +5074,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"330 µs ± 18.7 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
"138 µs ± 5.01 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
]
}
],
@ -5095,7 +5096,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"3.53 ms ± 75.2 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
"1.55 ms ± 56.7 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
]
}
],
@ -5130,7 +5131,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"15.5 ms ± 572 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
"20.8 ms ± 8.09 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
]
}
],
@ -5193,7 +5194,7 @@
}
},
"source": [
"The [OrderedDict](https://docs.python.org/3/library/collections.html#collections.OrderedDict) type may be used to create a `dict`-like object with the added feature that *explicitly* remembers the *insertion* order of its items.\n",
"The [OrderedDict](https://docs.python.org/3/library/collections.html#collections.OrderedDict) type may be used to create a `dict`-like object with the added feature of *explicitly* remembering the *insertion* order of its items.\n",
"\n",
"Let's look at a quick example: We create an `OrderedDict` object by passing an iterable of $2$-element iterables, one of the three ways to use [dict()](https://docs.python.org/3/library/functions.html#func-dict)."
]
@ -6360,8 +6361,8 @@
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-205-25fb5b5b2e5f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mchain\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m~/.pyenv/versions/anaconda3-2019.07/lib/python3.7/collections/__init__.py\u001b[0m in \u001b[0;36m__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 912\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 913\u001b[0m \u001b[0;32mpass\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 914\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__missing__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# support subclasses that define __missing__\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 915\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 916\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdefault\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\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[0;32m~/.pyenv/versions/anaconda3-2019.07/lib/python3.7/collections/__init__.py\u001b[0m in \u001b[0;36m__missing__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 904\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 905\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__missing__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\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[0;32m--> 906\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 907\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 908\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__getitem__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\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[0;32m~/.pyenv/versions/anaconda3-2019.10/lib/python3.7/collections/__init__.py\u001b[0m in \u001b[0;36m__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 914\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 915\u001b[0m \u001b[0;32mpass\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 916\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__missing__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# support subclasses that define __missing__\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 917\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 918\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdefault\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\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[0;32m~/.pyenv/versions/anaconda3-2019.10/lib/python3.7/collections/__init__.py\u001b[0m in \u001b[0;36m__missing__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 906\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 907\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__missing__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\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[0;32m--> 908\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 909\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 910\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__getitem__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\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[0;31mKeyError\u001b[0m: 10"
]
}
@ -6430,7 +6431,7 @@
{
"data": {
"text/plain": [
"139751998783784"
"139953088728672"
]
},
"execution_count": 207,
@ -6929,7 +6930,7 @@
}
],
"source": [
"1.0 in numbers"
"2.0 in numbers"
]
},
{
@ -7421,7 +7422,7 @@
{
"data": {
"text/plain": [
"139751998783784"
"139953088728672"
]
},
"execution_count": 243,
@ -8041,7 +8042,7 @@
}
},
"source": [
"This section provides some conference talks that go into great detail regarding the workings of the `dict` type."
"Next, we list some conference talks that go into great detail regarding the workings of the `dict` type."
]
},
{
@ -8068,7 +8069,7 @@
" "
],
"text/plain": [
"<IPython.lib.display.YouTubeVideo at 0x7f1a8c3e9d68>"
"<IPython.lib.display.YouTubeVideo at 0x7f495e8601d0>"
]
},
"execution_count": 261,
@ -8105,7 +8106,7 @@
" "
],
"text/plain": [
"<IPython.lib.display.YouTubeVideo at 0x7f1a8c2a9630>"
"<IPython.lib.display.YouTubeVideo at 0x7f495e2b4810>"
]
},
"execution_count": 262,
@ -8141,7 +8142,7 @@
" "
],
"text/plain": [
"<IPython.lib.display.YouTubeVideo at 0x7f1a8c214358>"
"<IPython.lib.display.YouTubeVideo at 0x7f495e249810>"
]
},
"execution_count": 263,
@ -8152,6 +8153,20 @@
"source": [
"YouTubeVideo(\"npw4s1QTmPg\", width=\"60%\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"The `dict` type's order has been worked on in many PEPs in recent years:\n",
"- [PEP 412](https://www.python.org/dev/peps/pep-0412/): Key-Sharing Dictionary\n",
"- [PEP 468](https://www.python.org/dev/peps/pep-0468/): Preserving the order of \\*\\*kwargs in a function\n",
"- [PEP 520](https://www.python.org/dev/peps/pep-0520/): Preserving Class Attribute Definition Order"
]
}
],
"metadata": {
@ -8170,7 +8185,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.7.4"
},
"livereveal": {
"auto_select": "code",
@ -8198,5 +8213,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

261
08_mappings_10_review.ipynb Normal file
View file

@ -0,0 +1,261 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Chapter 8: Mappings & Sets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Content Review"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings_00_content.ipynb) of the book. Then, work through the questions below."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Essay Questions "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions *briefly*!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1**: `dict` objects are well-suited **to model** discrete mathematical **functions** and to approximate continuous ones. What property of dictionaries is the basis for that claim, and how does it relate to functions in the mathematical sense?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q2**: Explain why **hash tables** are a **trade-off** between **computational speed** and **memory** usage!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3:** The `dict` type is an **iterable** that **contains** a **finite** number of key-value pairs. Despite that, why is it *not* considered a **sequence**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q4**: Whereas *key* **look-ups** in a `dict` object run in so-called **[constant time](https://en.wikipedia.org/wiki/Time_complexity#Constant_time)** (i.e., *extremely* fast), that does not hold for *reverse* look-ups. Why is that?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q5**: Why is it conceptually correct that the Python core developers do not implement **slicing** with the `[]` operator for `dict` objects?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q6**: **Memoization** is an essential concept to know to solve problems in the real world. Together with the idea of **recursion**, it enables us to solve problems in a \"backwards\" fashion *effectively*.\n",
"\n",
"\n",
"Compare the **recursive** formulation of `fibonacci()` in [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings_00_content.ipynb#\"Easy-at-third-Glance\"-Example:-Fibonacci-Numbers-%28revisited%29), the \"*Easy at third Glance*\" example, with the **iterative** version in [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb#\"Hard-at-first-Glance\"-Example:-Fibonacci-Numbers-%28revisited%29), the \"*Hard at first Glance*\" example!\n",
"\n",
"How are they similar and how do they differ?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7**: How are the `set` and the `dict` type related? How could we use the latter to mimic the former?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### True / False Questions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Motivate your answer with *one short* sentence!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q8**: We may *not* put `dict` objects inside other `dict` objects because they are **mutable**."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9**: **Mutable** objects (e.g., `list`) may generally *not* be used as keys in a `dict` object. However, if we collect, for example, `list` objects in a `tuple` object, the composite object becomes **hashable**."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q10**: **Mutability** of a `dict` object works until the underlying hash table becomes too crowded. Then, we cannot insert any items any more making the `dict` object effectively **immutable**. Luckily, that almost never happens in practice."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11**: A `dict` object's [update()](https://docs.python.org/3/library/stdtypes.html#dict.update) method only inserts key-value pairs whose key is *not* yet in the `dict` object. So, it does *not* overwrite anything."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q12**: The `set` type is both a mapping and a sequence."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View file

@ -8,221 +8,6 @@
"# Chapter 8: Mappings & Sets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Content Review"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings.ipynb) of the book. Then work through the twelve review questions."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Essay Questions "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Answer the following questions briefly with *at most* 300 characters per question!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q1**: `dict` objects are well-suited **to model** discrete mathematical **functions** and to approximate continuous ones. What property of dictionaries is the basis for that claim, and how does it relate to functions in the mathematical sense?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q2**: Explain why **hash tables** are a **trade-off** between **computational speed** and **memory** usage!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q3:** The `dict` type is an **iterable** that **contains** a **finite** number of key-value pairs. Despite that, why is it *not* considered a **sequence**?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q4**: Whereas *key* **look-ups** in a `dict` object run in so-called **[constant time](https://en.wikipedia.org/wiki/Time_complexity#Constant_time)** (i.e., *extremely* fast), that does not hold for *reverse* look-ups. Why is that?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q5**: Why is it conceptually correct that the Python core developers do not implement **slicing** with the `[]` operator for `dict` objects?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q6**: **Memoization** is an essential concept to know to solve problems in the real world. Together with the idea of **recursion**, it enables us to solve problems in a \"backwards\" fashion *effectively*.\n",
"\n",
"\n",
"Compare the **recursive** formulation of `fibonacci()` in [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings.ipynb#\"Easy-at-third-Glance\"-Example:-Fibonacci-Numbers-%28revisited%29), the \"*Easy at third Glance*\" example, with the **iterative** version in [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb#\"Hard-at-first-Glance\"-Example:-Fibonacci-Numbers-%28revisited%29), the \"*Hard at first Glance*\" example!\n",
"\n",
"How are they similar and how do they differ?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7**: How are the `set` and the `dict` type related? How could we use the latter to mimic the former?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### True / False Questions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Motivate your answer with *one short* sentence!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q8**: We may *not* put `dict` objects inside other `dict` objects because they are **mutable**."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9**: **Mutable** objects (e.g., `list`) may generally *not* be used as keys in a `dict` object. However, if we collect, for example, `list` objects in a `tuple` object, the composite object becomes **hashable**."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q10**: **Mutability** of a `dict` object works until the underlying hash table becomes too crowded. Then, we cannot insert any items any more making the `dict` object effectively **immutable**. Luckily, that almost never happens in practice."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q11**: A `dict` object's [update()](https://docs.python.org/3/library/stdtypes.html#dict.update) method only inserts key-value pairs whose key is *not* yet in the `dict` object. So, it does *not* overwrite anything."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q12**: The `set` type is both a mapping and a sequence."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -230,6 +15,13 @@
"## Coding Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 8](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings_00_content.ipynb) of the book. Then, work through the exercises below."
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -291,7 +83,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13.1**: Write a dictionary comprehension to derive a new `dict` object, called `brazilian_players`, that maps a Brazilian player's name to his position!"
"**Q1.1**: Write a dictionary comprehension to derive a new `dict` object, called `brazilian_players`, that maps a Brazilian player's name to his position!"
]
},
{
@ -316,7 +108,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13.2**: Generalize the code fragment into a `get_players()` function: Passed a `team` name, it returns a `dict` object like `brazilian_players`. Verify that the function works for the German team!"
"**Q1.2**: Generalize the code fragment into a `get_players()` function: Passed a `team` name, it returns a `dict` object like `brazilian_players`. Verify that the function works for the German team!"
]
},
{
@ -344,7 +136,7 @@
"source": [
"Often, we are given a `dict` object like the one returned from `get_players()`: It is characterized by the observation that a large set of unique keys (i.e., the players' names) is mapped onto a smaller set of non-unique values (i.e., the positions).\n",
"\n",
"**Q13.3**: Create a generic `invert()` function that swaps the keys and values of a `mapping` argument passed to it and returns them in a *new* `dict` object! Ensure that *no* key gets lost. Verify your implementation with the `brazilian_players` dictionary!\n",
"**Q1.3**: Create a generic `invert()` function that swaps the keys and values of a `mapping` argument passed to it and returns them in a *new* `dict` object! Ensure that *no* key gets lost. Verify your implementation with the `brazilian_players` dictionary!\n",
"\n",
"Hints: Think of this as a grouping operation. The *new* values are `list` or `tuple` objects that hold the original keys. You may want to use either the the [defaultdict](https://docs.python.org/3/library/collections.html#collections.defaultdict) type from the [collections](https://docs.python.org/3/library/collections.html) module in the [standard library](https://docs.python.org/3/library/index.html) or the [setdefault()](https://docs.python.org/3/library/stdtypes.html#dict.setdefault) method of the ordinary `dict` type."
]
@ -372,7 +164,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13.4**: Write a `score_at_minute()` function: It takes two arguments, `team` and `minute`, and returns the number of goals the `team` has scored up until this time in the game.\n",
"**Q1.4**: Write a `score_at_minute()` function: It takes two arguments, `team` and `minute`, and returns the number of goals the `team` has scored up until this time in the game.\n",
"\n",
"Hints: The function may reference the global `players` for simplicity. Earn bonus points if you can write this in a one-line expression using some *reduction* function and a *generator expression*."
]
@ -441,7 +233,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13.5**: Write a `goals_by_player()` function: It takes an argument like the global `players`, and returns a `dict` object mapping the players to the number of goals they scored.\n",
"**Q1.5**: Write a `goals_by_player()` function: It takes an argument like the global `players`, and returns a `dict` object mapping the players to the number of goals they scored.\n",
"\n",
"Hints: Do *not* \"hard code\" the names of the teams! Earn bonus points if you can solve it in a single dictionary comprehension."
]
@ -469,7 +261,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13.6**: Write a *dictionary comprehension* to filter out the players who did *not* score from the preceding result. Then, write a *set comprehension* that does the same but discards the number of goals scored.\n",
"**Q1.6**: Write a *dictionary comprehension* to filter out the players who did *not* score from the preceding result. Then, write a *set comprehension* that does the same but discards the number of goals scored.\n",
"\n",
"Hints: Reference the `goals_by_player()` function from before."
]
@ -496,7 +288,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13.7**: Write a `all_goals()` function: It takes one argument like the global `players` and returns a `list` object containing $2$-element `tuple` objects, where the first element is the minute a player scored and the second his name. The list should be sorted by the time.\n",
"**Q1.7**: Write a `all_goals()` function: It takes one argument like the global `players` and returns a `list` object containing $2$-element `tuple` objects, where the first element is the minute a player scored and the second his name. The list should be sorted by the time.\n",
"\n",
"Hints: You may want to use either the built-in [sorted()](https://docs.python.org/3/library/functions.html#sorted) function or the `list` type's [sort()](https://docs.python.org/3/library/stdtypes.html#list.sort) method. Earn bonus points if you can write a one-line expression with a *generator expression*."
]
@ -524,7 +316,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13.8**: Lastly, write a `summary()` function: It takes one argument like the global `players` and prints out a concise report of the goals, the score at the half, and the final result.\n",
"**Q1.8**: Lastly, write a `summary()` function: It takes one argument like the global `players` and prints out a concise report of the goals, the score at the half, and the final result.\n",
"\n",
"Hints: Use the `all_goals()` and `score_at_minute()` functions from before.\n",
"\n",
@ -575,7 +367,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
@ -592,5 +384,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}

View file

@ -13,23 +13,52 @@ studies** in the "field" of **data science**.
The "chapters" are written in [Jupyter notebooks](https://jupyter-notebook.readthedocs.io/en/stable/)
which are a de-facto standard for exchanging code and results among data
science professionals and researchers.
As such they can be viewed in a plain web browser:
They can be viewed in a plain web browser with the help of
[nbviewer](https://nbviewer.jupyter.org/):
- [00 - Start up](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/00_start_up.ipynb)
- [01 - Elements of a Program](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb)
- [02 - Functions & Modularization](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb)
- [03 - Conditionals & Exceptions](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals.ipynb)
- [04 - Recursion & Looping](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb)
- [05 - Bits & Numbers](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers.ipynb)
- [06 - Bytes & Text](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text.ipynb)
- [07 - Sequential Data](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences.ipynb)
- [08 - Mappings & Sets](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings.ipynb)
- *Introduction*: Start up
([content](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/00_start_up_00_content.ipynb)
| [review](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/00_start_up_10_review.ipynb)
| [exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/00_start_up_20_exercises.ipynb))
- **Part A: Expressing Logic**
- *Chapter 1*: Elements of a Program
([content](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_00_content.ipynb)
| [review](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_10_review.ipynb)
| [exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements_20_exercises.ipynb))
- *Chapter 2*: Functions & Modularization
([content](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_00_content.ipynb)
| [review](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_10_review.ipynb)
| [exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_20_exercises.ipynb))
- *Chapter 3*: Conditionals & Exceptions
([content](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_00_content.ipynb)
| [review](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_10_review.ipynb)
| [exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_20_exercises.ipynb))
- *Chapter 4*: Recursion & Looping
([content](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_content.ipynb)
| [review](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_10_review.ipynb)
| [exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_20_exercises.ipynb))
- **Part B: Managing Data and Memory**
- *Chapter 5*: Bits & Numbers
([content](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers_00_content.ipynb)
| [review](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers_10_review.ipynb)
| [exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers_20_exercises.ipynb))
- *Chapter 6*: Bytes & Text
([content](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text_00_content.ipynb)
| [review](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/06_text_10_review.ipynb))
- *Chapter 7*: Sequential Data
([content](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_00_content.ipynb)
| [review](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_10_review.ipynb)
| [exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/07_sequences_20_exercises.ipynb))
- *Chapter 8*: Mappings & Sets
([content](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings_00_content.ipynb)
| [review](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings_10_review.ipynb)
| [exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/08_mappings_20_exercises.ipynb))
However, it is recommended that students **install Python and Jupyter
locally** and run the code in the notebooks on their own.
This way, the student can play with the code and learn more efficiently.
Precise **installation instructions** are either in the [00th notebook](
https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/00_start_up.ipynb)
https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/00_start_up_00_content.ipynb)
or further below.
Feedback is encouraged and will be incorporated.