From 6c2cc48d3ee4680b94fe332bbaa9a43dcda38cee Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 10:41:55 +0200 Subject: [PATCH 01/14] Re-order exercises and review --- README.md | 8 ++++---- .../{02_exercises.ipynb => 01_exercises.ipynb} | 0 chapter_00_intro/{01_review.ipynb => 02_review.ipynb} | 0 3 files changed, 4 insertions(+), 4 deletions(-) rename chapter_00_intro/{02_exercises.ipynb => 01_exercises.ipynb} (100%) rename chapter_00_intro/{01_review.ipynb => 02_review.ipynb} (100%) diff --git a/README.md b/README.md index 208a5bd..a9cb8c8 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,11 @@ They can be viewed in a web browser [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_00_intro/00_content.ipynb) [](https://www.youtube.com/watch?v=YTU8jaG27Xk&list=PL-2JV1G3J10lQ2xokyQowcRJI5jjNfW7f) | - [review ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_00_intro/01_review.ipynb) - [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_00_intro/01_review.ipynb) + [exercises ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_00_intro/01_exercises.ipynb) + [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_00_intro/01_exercises.ipynb) | - [exercises ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_00_intro/02_exercises.ipynb) - [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_00_intro/02_exercises.ipynb) + [review ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_00_intro/02_review.ipynb) + [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_00_intro/02_review.ipynb) ) diff --git a/chapter_00_intro/02_exercises.ipynb b/chapter_00_intro/01_exercises.ipynb similarity index 100% rename from chapter_00_intro/02_exercises.ipynb rename to chapter_00_intro/01_exercises.ipynb diff --git a/chapter_00_intro/01_review.ipynb b/chapter_00_intro/02_review.ipynb similarity index 100% rename from chapter_00_intro/01_review.ipynb rename to chapter_00_intro/02_review.ipynb From 92dde01e0c51bf98a891f6c1480b79d1b3bf91f7 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 11:02:29 +0200 Subject: [PATCH 02/14] Streamline text --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a9cb8c8..f0e0087 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,11 @@ This project is a *thorough* introductory course ### Table of Contents -The materials are designed to resemble a book. -They can be viewed in a web browser +The materials are designed to resemble an *interactive* book. +It is recommended + to follow the [installation instructions](https://github.com/webartifex/intro-to-python#installation) below + and work through the content on one's own computer. +Alternatively, the content can be viewed in a web browser either statically (i.e., read-only) on [nbviewer ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/tree/develop/) or interactively (i.e., code can be executed) on [Binder ](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab). **Video** presentations on the content are available From 2dfc9540b68072ee13ead399c60e648145299acb Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 11:10:37 +0200 Subject: [PATCH 03/14] Make YouTube references less prominent - the current video lectures regard the old one-notebook-per-chapter structure of the project - as the new structure involves several smaller notebooks per chapter, there is no one-on-one correspondence to the YouTube lectures any more => only reference the YouTube playlist once in the README.md --- README.md | 12 ++-- chapter_00_intro/00_content.ipynb | 106 ------------------------------ 2 files changed, 8 insertions(+), 110 deletions(-) diff --git a/README.md b/README.md index f0e0087..18df65d 100644 --- a/README.md +++ b/README.md @@ -13,15 +13,11 @@ It is recommended Alternatively, the content can be viewed in a web browser either statically (i.e., read-only) on [nbviewer ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/tree/develop/) or interactively (i.e., code can be executed) on [Binder ](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab). -**Video** presentations on the content are available - either via the individual links to [YouTube ](https://www.youtube.com) below - or this [playlist ](https://www.youtube.com/playlist?list=PL-2JV1G3J10lQ2xokyQowcRJI5jjNfW7f). - *Chapter 0*: Introduction ( [content ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_00_intro/00_content.ipynb) [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_00_intro/00_content.ipynb) - [](https://www.youtube.com/watch?v=YTU8jaG27Xk&list=PL-2JV1G3J10lQ2xokyQowcRJI5jjNfW7f) | [exercises ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_00_intro/01_exercises.ipynb) [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_00_intro/01_exercises.ipynb) @@ -31,6 +27,14 @@ Alternatively, the content can be viewed in a web browser ) +#### Videos + +Presentations of the chapters are available on this [YouTube playlist ](https://www.youtube.com/playlist?list=PL-2JV1G3J10lQ2xokyQowcRJI5jjNfW7f). +The recordings are about 25 hours long in total + and were made in spring 2020 + after a corresponding in-class Bachelor course was cancelled due to Corona. + + ### Objective The **main goal** is to **prepare** students diff --git a/chapter_00_intro/00_content.ipynb b/chapter_00_intro/00_content.ipynb index ae68a81..bbc1dce 100644 --- a/chapter_00_intro/00_content.ipynb +++ b/chapter_00_intro/00_content.ipynb @@ -796,112 +796,6 @@ "source": [ "" ] - }, - { - "cell_type": "markdown", - "metadata": { - "slideshow": { - "slide_type": "skip" - } - }, - "source": [ - "## Further Resources" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "slideshow": { - "slide_type": "skip" - } - }, - "source": [ - "A lecture-style **video presentation** of this chapter is integrated below (cf., the [video ](https://www.youtube.com/watch?v=YTU8jaG27Xk&list=PL-2JV1G3J10lQ2xokyQowcRJI5jjNfW7f) or the entire [playlist ](https://www.youtube.com/playlist?list=PL-2JV1G3J10lQ2xokyQowcRJI5jjNfW7f))." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "slideshow": { - "slide_type": "skip" - } - }, - "outputs": [ - { - "data": { - "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAUDBAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChALCAgOCggIDRYNDhERExMTCAsWGBYSGBASExIBBQUFCAcIDwkJDxgVERUWFxcYExMYGBgVFRgWFRYWGBcVGxIaEhMXFRoYGBISFRcVFRUVFRUVFRUVGBUSFxIVFf/AABEIAWgB4AMBIgACEQEDEQH/xAAdAAEAAgIDAQEAAAAAAAAAAAAABgcFCAIDBAEJ/8QAURAAAQQBAgMBCQgRAgUEAgMAAQACAwQRBRIGEyExBxQYIjJBVZTVCBUXUVJhk9QjMzVCU1RxcnN0dYGSsbKz05G0FiQ2YrU0gqGiY3YlQ0X/xAAcAQEAAgMBAQEAAAAAAAAAAAAAAgQBAwUHBgj/xAA9EQABAwIDBQUGBAYBBQEAAAABAAIRAyEEEjEFQVFhcRMVU4GRBiIyocHwFjRysRQ1QlLR4fEjM0NigpL/2gAMAwEAAhEDEQA/ANMkREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREWzPgVcVfj/D/AK1qPs5PAq4q/H+H/WtR9nIi1mRbM+BVxV+P8P8ArWo+zk8Crir8f4f9a1H2ciLWZFsz4FXFX4/w/wCtaj7OTwKuKvx/h/1rUfZyItZkWzPgVcVfj/D/AK1qPs5PAq4q/H+H/WtR9nIi1mRbM+BVxV+P8P8ArWo+zk8Crir8f4f9a1H2ciLWZFsz4FXFX4/w/wCtaj7OTwKuKvx/h/1rUfZyItZkWzPgVcVfj/D/AK1qPs5PAq4q/H+H/WtR9nIi1mRbM+BVxV+P8P8ArWo+zk8Crir8f4f9a1H2ciLWZFsz4FXFX4/w/wCtaj7OTwKuKvx/h/1rUfZyItZkWzPgVcVfj/D/AK1qPs5PAq4q/H+H/WtR9nIi1mRbM+BVxV+P8P8ArWo+zk8Crir8f4f9a1H2ciLWZFsz4FXF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hodQ0EBkkco21dQ8qJ4e0HOodmWhZBgrB0X6DItAPDV4q9H8P+q6j7RTw1eKvR/D/quo+0VhZW/6LQDw1eKvR/D/AKrqPtFPDV4q9H8P+q6j7RRFv+i0A8NXir0fw/6rqPtFPDV4q9H8P+q6j7RRFv8AotAPDV4q9H8P+q6j7RTw1eKvR/D/AKrqPtFEW/6LQDw1eKvR/D/quo+0U8NXir0fw/6rqPtFEW/6LQDw1eKvR/D/AKrqPtFPDV4q9H8P+q6j7RRFv+i0A8NXir0fw/6rqPtFPDV4q9H8P+q6j7RRFv8AotAPDV4q9H8P+q6j7RTw1eKvR/D/AKrqPtFEW/6LQDw1eKvR/D/quo+0U8NXir0fw/6rqPtFEW/6LQDw1eKvR/D/AKrqPtFPDV4q9H8P+q6j7RRFv+i0A8NXir0fw/6rqPtFPDV4q9H8P+q6j7RRFv8AotAPDV4q9H8P+q6j7RTw1eKvR/D/AKrqPtFEW/6LQDw1eKvR/D/quo+0U8NXir0fw/6rqPtFEW/682q/aJ/0Mn9DloT4avFXo/h/1XUfaK4WPdo8UvY9hoaBh7XNOKuo5w4EHGdR7eqItaURERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERf/2Q==\n", - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from IPython.display import YouTubeVideo\n", - "YouTubeVideo(\"YTU8jaG27Xk\", width=\"60%\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "slideshow": { - "slide_type": "skip" - } - }, - "source": [ - "Also, to see some common shortcuts in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/), find a **video tutorial** below." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "slideshow": { - "slide_type": "skip" - } - }, - "outputs": [ - { - "data": { - "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAUDBAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChALCAgOCggIDRYNDhERExMTCAsWGBYSGBASExIBBQUFCAcIDwkJDxgVERUWFxcYExMYGBgVFRgWFRYWGBcVGxIaEhMXFRoYGBISFRcVFRUVFRUVFRUVGBUSFxIVFf/AABEIAWgB4AMBIgACEQEDEQH/xAAdAAEAAgIDAQEAAAAAAAAAAAAABgcFCAIDBAEJ/8QAURAAAQQBAgMBCQgRAgUEAgMAAQACAwQRBRIGEyExBxQYIjJBVZTVCBUXUVJhk9QjMzVCU1RxcnN0dYGSsbKz05G0FiQ2YrU0gqGiY3YlQ0X/xAAcAQEAAgMBAQEAAAAAAAAAAAAAAgQBAwUHBgj/xAA9EQABAwIDBQUGBAYBBQEAAAABAAIRAyEEEjEFQVFhcRMVU4GRBiIyocHwFjRysRQ1QlLR4fEjM0NigpL/2gAMAwEAAhEDEQA/ANMkREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREWzPgVcVfj/D/AK1qPs5PAq4q/H+H/WtR9nIi1mRbM+BVxV+P8P8ArWo+zk8Crir8f4f9a1H2ciLWZFsz4FXFX4/w/wCtaj7OTwKuKvx/h/1rUfZyItZkWzPgVcVfj/D/AK1qPs5PAq4q/H+H/WtR9nIi1mRbM+BVxV+P8P8ArWo+zk8Crir8f4f9a1H2ciLWZFsz4FXFX4/w/wCtaj7OTwKuKvx/h/1rUfZyItZkWzPgVcVfj/D/AK1qPs5PAq4q/H+H/WtR9nIi1mRbM+BVxV+P8P8ArWo+zk8Crir8f4f9a1H2ciLWZFsz4FXFX4/w/wCtaj7OTwKuKvx/h/1rUfZyItZkWzPgVcVfj/D/AK1qPs5PAq4q/H+H/WtR9nIi1mRbM+BVxV+P8P8ArWo+zk8Crir8f4f9a1H2ciLWZFsz4FXF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hodQ0EBkkco21dQ8qJ4e0HOodmWhZBgrB0X6DItAPDV4q9H8P+q6j7RTw1eKvR/D/quo+0VhZW/6LQDw1eKvR/D/AKrqPtFPDV4q9H8P+q6j7RRFv+i0A8NXir0fw/6rqPtFPDV4q9H8P+q6j7RRFv8AotAPDV4q9H8P+q6j7RTw1eKvR/D/AKrqPtFEW/6LQDw1eKvR/D/quo+0U8NXir0fw/6rqPtFEW/6LQDw1eKvR/D/AKrqPtFPDV4q9H8P+q6j7RRFv+i0A8NXir0fw/6rqPtFPDV4q9H8P+q6j7RRFv8AotAPDV4q9H8P+q6j7RTw1eKvR/D/AKrqPtFEW/6LQDw1eKvR/D/quo+0U8NXir0fw/6rqPtFEW/6LQDw1eKvR/D/AKrqPtFPDV4q9H8P+q6j7RRFv+i0A8NXir0fw/6rqPtFPDV4q9H8P+q6j7RRFv8AotAPDV4q9H8P+q6j7RTw1eKvR/D/AKrqPtFEW/6LQDw1eKvR/D/quo+0U8NXir0fw/6rqPtFEW/682q/aJ/0Mn9DloT4avFXo/h/1XUfaK4WPdo8UvY9hoaBh7XNOKuo5w4EHGdR7eqItaURERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERf/2Q==\n", - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "YouTubeVideo(\"5GGyKq1F_5c\", width=\"60%\")" - ] } ], "metadata": { From 4c7f7f4387911ba83c2c0458749f3c28ba9febb1 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 11:15:33 +0200 Subject: [PATCH 04/14] Store notebooks with execution output --- chapter_00_intro/00_content.ipynb | 37 ++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/chapter_00_intro/00_content.ipynb b/chapter_00_intro/00_content.ipynb index bbc1dce..0d52716 100644 --- a/chapter_00_intro/00_content.ipynb +++ b/chapter_00_intro/00_content.ipynb @@ -220,26 +220,45 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "slideshow": { "slide_type": "slide" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "1 + 2" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "slideshow": { "slide_type": "fragment" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello World\n" + ] + } + ], "source": [ "print(\"Hello World\")" ] @@ -267,7 +286,15 @@ "slide_type": "skip" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python 3.8.6\n" + ] + } + ], "source": [ "!python --version" ] From 76fcfc54eace1db03134bb7c09fbc2606069f2f9 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 12:05:50 +0200 Subject: [PATCH 05/14] Streamline text --- chapter_00_intro/01_exercises.ipynb | 2 +- chapter_00_intro/02_review.ipynb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chapter_00_intro/01_exercises.ipynb b/chapter_00_intro/01_exercises.ipynb index 28a2cbf..7f51a1d 100644 --- a/chapter_00_intro/01_exercises.ipynb +++ b/chapter_00_intro/01_exercises.ipynb @@ -25,7 +25,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The exercises below assume that you have read [Chapter 0 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_00_intro/00_content.ipynb) in the book." + "The exercises below assume that you have read [Chapter 0 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_00_intro/00_content.ipynb)." ] }, { diff --git a/chapter_00_intro/02_review.ipynb b/chapter_00_intro/02_review.ipynb index 2ea6b98..0f75bfe 100644 --- a/chapter_00_intro/02_review.ipynb +++ b/chapter_00_intro/02_review.ipynb @@ -18,7 +18,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The questions below assume that you have read [Chapter 0 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_00_intro/00_content.ipynb) in the book.\n", + "The questions below assume that you have read [Chapter 0 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_00_intro/00_content.ipynb).\n", "\n", "Be concise in your answers! Most questions can be answered in *one* sentence." ] From 0bb99a13b1f6a578d85323efc4df9908c84d0660 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 12:08:58 +0200 Subject: [PATCH 06/14] Add initial version of chapter 01, part 1 --- README.md | 6 + chapter_00_intro/00_content.ipynb | 2 +- chapter_01_elements/00_content.ipynb | 2188 ++++++++++++++++++++++++++ 3 files changed, 2195 insertions(+), 1 deletion(-) create mode 100644 chapter_01_elements/00_content.ipynb diff --git a/README.md b/README.md index 18df65d..de59194 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,12 @@ Alternatively, the content can be viewed in a web browser [review ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_00_intro/02_review.ipynb) [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_00_intro/02_review.ipynb) ) +- **Part A: Expressing Logic** + - *Chapter 1*: Elements of a Program + ( + [content 1 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/00_content.ipynb) + [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/00_content.ipynb) + ) #### Videos diff --git a/chapter_00_intro/00_content.ipynb b/chapter_00_intro/00_content.ipynb index 0d52716..fc6a255 100644 --- a/chapter_00_intro/00_content.ipynb +++ b/chapter_00_intro/00_content.ipynb @@ -750,7 +750,7 @@ "**Part A: Expressing Logic**\n", "\n", "- What is a programming language? What kind of words exist?\n", - " - *Chapter 1*: Elements of a Program\n", + " - *Chapter 1*: [Elements of a Program ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/00_content.ipynb)\n", " - *Chapter 2*: Functions & Modularization\n", "- What is the flow of execution? How can we form sentences from words?\n", " - *Chapter 3*: Conditionals & Exceptions\n", diff --git a/chapter_01_elements/00_content.ipynb b/chapter_01_elements/00_content.ipynb new file mode 100644 index 0000000..ad71aa9 --- /dev/null +++ b/chapter_01_elements/00_content.ipynb @@ -0,0 +1,2188 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Clear All Outputs*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *before* reading this notebook to reset its output. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/00_content.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Chapter 1: Elements of a Program" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Do you remember how you first learned to speak in your mother tongue? Probably not. No one's memory goes back that far. Your earliest memory as a child should probably be around the age of three or four years old when you could already say simple things and interact with your environment. Although you did not know any grammar rules yet, other people just understood what you said. At least most of the time.\n", + "\n", + "It is intuitively best to take the very mindset of a small child when learning a new language. And a programming language is no different from that. This first chapter introduces simplistic examples and we accept them as they are *without* knowing any of the \"grammar\" rules yet. Then, we analyze them in parts and slowly build up our understanding.\n", + "\n", + "Consequently, if parts of this chapter do not make sense right away, let's not worry too much. Besides introducing the basic elements, it also serves as an outlook for what is to come. So, many terms and concepts used here are deconstructed in great detail in the following chapters." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Example: Averaging all even Numbers in a List" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "As our introductory example, we want to calculate the *average* of all *evens* in a **list** of whole numbers: `[7, 11, 8, 5, 3, 12, 2, 6, 9, 10, 1, 4]`.\n", + "\n", + "While we are used to finding an [analytical solution](https://math.stackexchange.com/questions/935405/what-s-the-difference-between-analytical-and-numerical-approaches-to-problems/935446#935446) in math (i.e., derive some equation with \"pen and paper\"), we solve this task *programmatically* instead.\n", + "\n", + "We start by creating a list called `numbers` that holds all the individual numbers between **brackets** `[` and `]`." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "scrolled": true, + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "numbers = [7, 11, 8, 5, 3, 12, 2, 6, 9, 10, 1, 4]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "To verify that something happened in our computer's memory, we **reference** `numbers`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[7, 11, 8, 5, 3, 12, 2, 6, 9, 10, 1, 4]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "So far, so good. Let's see how the desired **computation** could be expressed as a **sequence of instructions** in the next code cell.\n", + "\n", + "Intuitively, the line `for number in numbers` describes a \"loop\" over all the numbers in the `numbers` list, one at a time.\n", + "\n", + "The `if number % 2 == 0` may look confusing at first sight. Both `%` and `==` must have an unintuitive meaning here. Luckily, the **comment** in the same line after the `#` symbol has the answer: The program does something only for an even `number`.\n", + "\n", + "In particular, it increases `count` by `1` and adds the current `number` onto the [running ](https://en.wikipedia.org/wiki/Running_total) `total`. Both `count` and `number` are **initialized** to `0` and the single `=` symbol reads as \"... is *set* equal to ...\". It cannot indicate a mathematical equation as, for example, `count` is generally *not* equal to `count + 1`.\n", + "\n", + "Lastly, the `average` is calculated as the ratio of the final **values** of `total` and `count`. Overall, we divide the sum of all even numbers by their count: This is nothing but the definition of an average.\n", + "\n", + "The lines of code \"within\" the `for` and `if` **statements** are **indented** and aligned with multiples of *four spaces*: This shows immediately how the lines relate to each other." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "count = 0 # initialize variables to keep track of the\n", + "total = 0 # running total and the count of even numbers\n", + "\n", + "for number in numbers:\n", + " if number % 2 == 0: # only work with even numbers\n", + " count = count + 1\n", + " total = total + number\n", + "\n", + "average = total / count" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "We do not see any **output** yet but obtain the value of `average` by referencing it again." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "7.0" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "average" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Output in a Jupyter Notebook" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Only two of the previous four code cells generate an **output** while two remained \"silent\" (i.e., nothing appears below the cell after running it).\n", + "\n", + "By default, Jupyter notebooks only show the value of the **expression** in the last line of a code cell. And, this output may also be suppressed by ending the last line with a semicolon `;`." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'I am feeling great :-)'" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"Hello, World!\"\n", + "\"I am feeling great :-)\"" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "\"I am invisible!\";" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "To see any output other than that, we use the built-in [print() ](https://docs.python.org/3/library/functions.html#print) **function**. Here, the parentheses `()` indicate that we **call** (i.e., \"execute\") code written somewhere else." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello, World!\n", + "I am feeling great :-)\n" + ] + } + ], + "source": [ + "print(\"Hello, World!\")\n", + "print(\"I am feeling great :-)\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Outside Jupyter notebooks, the semicolon `;` is used as a **separator** between statements that must otherwise be on a line on their own. However, it is *not* considered good practice to use it as it makes code less readable." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello, World!\n", + "I am feeling great :-)\n" + ] + } + ], + "source": [ + "print(\"Hello, World!\"); print(\"I am feeling great :-)\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## (Arithmetic) Operators" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Python comes with many built-in **[operators ](https://docs.python.org/3/reference/lexical_analysis.html#operators)**: They are **tokens** (i.e., \"symbols\") that have a special meaning to the Python interpreter.\n", + "\n", + "The arithmetic operators either \"operate\" with the number immediately following them, so-called **unary** operators (e.g., negation), or \"process\" the two numbers \"around\" them, so-called **binary** operators (e.g., addition).\n", + "\n", + "By definition, operators on their own have *no* permanent **side effects** in the computer's memory. Although the code cells in this section do indeed create *new* numbers in memory (e.g., `77 + 13` creates `90`), they are immediately \"forgotten\" as they are not stored in a **variable** like `numbers` or `average` above. We develop this thought further in the second part of this chapter when we compare **expressions** with **statements**.\n", + "\n", + "Let's see some examples of operators. We start with the binary `+` and the `-` operators for addition and subtraction. Binary operators mimic what mathematicians call [infix notation ](https://en.wikipedia.org/wiki/Infix_notation) and have the expected meaning." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "90" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "77 + 13" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "8" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "101 - 93" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The `-` operator may be used as a unary operator as well. Then, it unsurprisingly flips the sign of a number." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "-1" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "-1" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "When we compare the output of the `*` and `/` operators for multiplication and division, we note the subtle *difference* between the `42` and the `42.0`: They are the *same* number represented as a *different* **data type**." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "42" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "2 * 21" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "42.0" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "84 / 2" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The so-called **floor division operator** `//` always \"rounds\" to an integer and is thus also called **integer division operator**. It is an example of an arithmetic operator we commonly do not know from high school mathematics." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "42" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "84 // 2" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "42" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "85 // 2" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Even though it appears that the `//` operator **truncates** (i.e., \"cuts off\") the decimals so as to effectively round down (i.e., the `42.5` became `42` in the previous code cell), this is *not* the case: The result is always \"rounded\" towards minus infinity!" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "-43" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "-85 // 2" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "To obtain the remainder of a division, we use the **modulo operator** `%`." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "85 % 2" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The remainder is `0` *only if* a number is *divisible* by another.\n", + "\n", + "A popular convention in both computer science and mathematics is to abbreviate \"only if\" as \"iff\", which is short for \"**[if and only if ](https://en.wikipedia.org/wiki/If_and_only_if)**.\" The iff means that a remainder of `0` implies that a number is divisible by another but also that a number's being divisible by another implies a remainder of `0`. The implication goes in *both* directions!\n", + "\n", + "So, `49` is divisible by `7`." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "49 % 7" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Modulo division is also useful if we want to extract the last couple of digits in a large integer." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "9" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "789 % 10" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "89" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "789 % 100" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The built-in [divmod() ](https://docs.python.org/3/library/functions.html#divmod) function combines the integer and modulo divisions into one step. However, grammatically this is *not* an operator but a function. Also, [divmod() ](https://docs.python.org/3/library/functions.html#divmod) returns a \"pair\" of integers and not a single one." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(4, 2)" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "divmod(42, 10)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Raising a number to a power is performed with the **exponentiation operator** `**`. It is different from the `^` operator other programming languages may use and that also exists in Python with a *different* meaning." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "8" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "2 ** 3" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The standard [order of precedence ](https://docs.python.org/3/reference/expressions.html#operator-precedence) from mathematics applies (i.e., [PEMDAS](http://mathworld.wolfram.com/PEMDAS.html) rule) when several operators are combined." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "18" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "3 ** 2 * 2 " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Parentheses help avoid confusion and take the role of a **delimiter** here." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "18" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(3 ** 2) * 2" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "81" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "3 ** (2 * 2)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Some programmers also use \"style\" conventions. For example, we might play with the **whitespace**, which is an umbrella term that refers to any non-printable sign like spaces, tabs, or the like. However, this is *not* a good practice and parentheses convey a much clearer picture." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "18" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "3**2 * 2 # bad style; it is better to use parentheses here" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "There exist many non-mathematical operators that are introduced throughout this book, together with the concepts they implement. They often come in a form different from the unary and binary ones mentioned above." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Operator Overloading" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Python **overloads** certain operators. For example, you may not only \"add\" numbers but also text: This is called **concatenation**." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "greeting = \"Hi \"\n", + "audience = \"class\"" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Hi class'" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "greeting + audience" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Multiplying text with a whole number also works." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi '" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "10 * greeting" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Objects vs. Types vs. Values" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Python is a so-called **object-oriented** language, which is a paradigm of organizing a program's memory.\n", + "\n", + "An **object** may be viewed as a \"bag\" of $0$s and $1$s in a given memory location. The $0$s and $1$s in a bag make up the object's **value**. There exist different **types** of bags, and each type comes with its own rules how the $0$s and $1$s are interpreted and may be worked with.\n", + "\n", + "So, an object *always* has *three* main characteristics. Let's look at the following examples and work them out." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "a = 42\n", + "b = 42.0\n", + "c = \"Python rocks\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Identity / \"Memory Location\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The built-in [id() ](https://docs.python.org/3/library/functions.html#id) function shows an object's \"address\" in memory." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "94371758832672" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "id(a)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "140673826512720" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "id(b)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "140673817995952" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "id(c)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "These addresses are *not* meaningful for anything other than checking if two variables reference the *same* object.\n", + "\n", + "Obviously, `a` and `b` have the same *value* as revealed by the **equality operator** `==`: We say `a` and `b` \"evaluate equal.\" The resulting `True` - and the `False` further below - is yet another data type, a so-called **boolean**. We look into them in [Chapter 3 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_03_conditionals/00_content.ipynb#Boolean-Expressions)." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a == b" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "On the contrary, `a` and `b` are *different* objects as the **identity operator** `is` shows: They are stored at *different* addresses in the memory." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a is b" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "If we want to check the opposite case, we use the negated version of the `is` operator, namely `is not`." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a is not b" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### (Data) Type / \"Behavior\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The [type() ](https://docs.python.org/3/library/functions.html#type) built-in shows an object's type. For example, `a` is an integer (i.e., `int`) while `b` is a so-called [floating-point number ](https://en.wikipedia.org/wiki/Floating-point_arithmetic) (i.e., `float`)." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "int" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(a)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "float" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(b)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Different types imply different behaviors for the objects. The `b` object, for example, may be \"asked\" if it is a whole number with the [is_integer() ](https://docs.python.org/3/library/stdtypes.html#float.is_integer) \"functionality\" that comes with *every* `float` object.\n", + "\n", + "Formally, we call such type-specific functionalities **methods** (i.e., as opposed to functions) and we look at them in detail in [Chapter 10 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_10_classes/00_content.ipynb). For now, it suffices to know that we access them with the **dot operator** `.` on the object. Of course, `b` is a whole number, which the boolean object `True` tells us." + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b.is_integer()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "For an `int` object, this [is_integer() ](https://docs.python.org/3/library/stdtypes.html#float.is_integer) check does *not* make sense as we already know it is an `int`: We see the `AttributeError` below as `a` does not even know what `is_integer()` means." + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'int' object has no attribute 'is_integer'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_integer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m: 'int' object has no attribute 'is_integer'" + ] + } + ], + "source": [ + "a.is_integer()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The `c` object is a so-called **string** type (i.e., `str`), which is Python's way of representing text. Strings also come with peculiar behaviors, for example, to make a text lower or upper case." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "str" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(c)" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'python rocks'" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c.lower()" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'PYTHON ROCKS'" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c.upper()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Value / (Semantic) \"Meaning\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Almost trivially, every object also has a value to which it **evaluates** when referenced. We think of the value as the **conceptual idea** of what the $0$s and $1$s in the bag mean to *humans*. In other words, an object's value regards its *semantic* meaning.\n", + "\n", + "For built-in data types, Python prints out an object's value as a so-called **[literal ](https://docs.python.org/3/reference/lexical_analysis.html#literals)**: This means that we may copy and paste the value back into a code cell and create a *new* object with the *same* value." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "42" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "42.0" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "In this book, we follow the convention of creating strings with **double quotes** `\"` instead of the **single quotes** `'` to which Python defaults in its *literal* notation for `str` objects. Both types of quotes may be used interchangeably. So, the `\"Python rocks\"` from above and `'Python rocks'` below create two objects that evaluate equal (i.e., `\"Python rocks\" == 'Python rocks'`)." + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Python rocks'" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Formal vs. Natural Languages" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Just like the language of mathematics is good at expressing relationships among numbers and symbols, any programming language is just a formal language that is good at expressing computations.\n", + "\n", + "Formal languages come with their own \"grammatical rules\" called **syntax**." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Syntax Errors" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "If we do not follow the rules, the code cannot be **parsed** correctly, i.e., the program does not even start to run but **raises** a **syntax error** indicated as `SyntaxError` in the output. Computers are very dumb in the sense that the slightest syntax error leads to the machine not understanding our code.\n", + "\n", + "If we were to write an accounting program that adds up currencies, we would, for example, have to model dollar prices as `float` objects as the dollar symbol cannot be understood by Python." + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (, line 1)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m 3.99 $ + 10.40 $\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "3.99 $ + 10.40 $" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Python requires certain symbols at certain places (e.g., a `:` is missing here)." + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (, line 1)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m for number in numbers\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "for number in numbers\n", + " print(number)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Furthermore, it relies on whitespace (i.e., indentation), unlike many other programming languages. The `IndentationError` below is just a particular type of a `SyntaxError`." + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "ename": "IndentationError", + "evalue": "expected an indented block (, line 2)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m2\u001b[0m\n\u001b[0;31m print(number)\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mIndentationError\u001b[0m\u001b[0;31m:\u001b[0m expected an indented block\n" + ] + } + ], + "source": [ + "for number in numbers:\n", + "print(number)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Runtime Errors" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Syntax errors are easy to find as the code does *not* even run in the first place.\n", + "\n", + "However, there are also so-called **runtime errors** that occur whenever otherwise (i.e., syntactically) correct code does not run because of invalid input. Runtime errors are also often referred to as **exceptions**.\n", + "\n", + "This example does not work because just like in the \"real\" world, Python does not know how to divide by `0`. The syntactically correct code leads to a `ZeroDivisionError`." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "ename": "ZeroDivisionError", + "evalue": "division by zero", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;36m1\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mZeroDivisionError\u001b[0m: division by zero" + ] + } + ], + "source": [ + "1 / 0" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Semantic Errors" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "So-called **semantic errors**, on the contrary, are hard to spot as they do *not* crash the program. The only way to find such errors is to run a program with test input for which we can predict the output. However, testing software is a whole discipline on its own and often very hard to do in practice.\n", + "\n", + "The cell below copies our first example from above with a \"tiny\" error. How fast could you have spotted it without the comment?" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "code_folding": [], + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "count = 0\n", + "total = 0\n", + "\n", + "for number in numbers:\n", + " if number % 2 == 0:\n", + " count = count + 1\n", + " total = total + count # count is wrong here, it should be number\n", + "\n", + "average = total / count" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3.5" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "average" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Systematically finding errors is called **debugging**. For the history of the term, see this [article ](https://en.wikipedia.org/wiki/Debugging)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Best Practices" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Thus, adhering to just syntax rules is *never* enough. Over time, **best practices** and **style guides** were created to make it less likely for a developer to mess up a program and also to allow \"onboarding\" him as a contributor to an established code base, often called **legacy code**, faster. These rules are *not* enforced by Python itself: Badly styled code still runs. At the very least, Python programs should be styled according to [PEP 8 ](https://www.python.org/dev/peps/pep-0008/) and documented \"inline\" (i.e., in the code itself) according to [PEP 257 ](https://www.python.org/dev/peps/pep-0257/).\n", + "\n", + "An easier to read version of PEP 8 is [here](https://pep8.org/). The video below features a well known **[Pythonista](https://en.wiktionary.org/wiki/Pythonista)** talking about the importance of code style." + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAUDBAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChANCAgOCggIDRUNDhERExMTCAsWGBYSGBASExIBBQUFCAcIDwkJDxUVEBUVFhUVFRUSFRUVFRISEhUVFRUVFRUVFRUVFRIVEhUVFRUVFRUVFRUVFRUVFRUVFRUVFf/AABEIAWgB4AMBIgACEQEDEQH/xAAcAAEAAgMBAQEAAAAAAAAAAAAABgcEBQgDAgH/xABfEAABAwICBQUHDgsGAggFBQABAAIDBBEFEgYHEyExQVFTYZIUFyJxgZHTCCMyNUJSYnJzdKGxs8EVJCUzNIKDorK0wkNjZJOjw9HwJ1RVlKS10uEWJmWVpTY3RFZ1/8QAHAEBAAIDAQEBAAAAAAAAAAAAAAUGAwQHAgEI/8QAQBEAAQIDAwgGBwcEAwEAAAAAAQACAwQRBSExBhITQVFxkcEWYWKBobEUIjRTcpLRIyQyMzWC4QdSsvBCovEV/9oADAMBAAIRAxEAPwDjJEREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREX6innexrOmpu3L6JO9jWdNTduX0SUKmuj0/7p3BQNFPO9jWdNTduX0Sd7Gs6am7cvokoU6PT/uncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P8AuncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P+6dwUDRTzvY1nTU3bl9EnexrOmpu3L6JKFOj0/7p3BQNFPO9jWdNTduX0Sd7Gs6am7cvokoU6PT/uncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P8AuncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P+6dwUDRTzvY1nTU3bl9EnexrOmpu3L6JKFOj0/7p3BQNFPO9jWdNTduX0Sd7Gs6am7cvokoU6PT/uncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P8AuncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P+6dwUDRTzvY1nTU3bl9EnexrOmpu3L6JKFOj0/7p3BQNFPO9jWdNTduX0Sd7Gs6am7cvokoU6PT/uncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P8AuncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P+6dwUDRTzvY1nTU3bl9EnexrOmpu3L6JKFOj0/7p3BQNFPO9jWdNTduX0Sd7Gs6am7cvokoU6PT/uncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P8AuncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P+6dwUDRTzvY1nTU3bl9EnexrOmpu3L6JKFOj0/7p3BQNFPO9jWdNTduX0Sd7Gs6am7cvokoU6PT/uncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P8AuncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P+6dwUDRTzvY1nTU3bl9EnexrOmpu3L6JKFOj0/7p3BQNFPO9jWdNTduX0Sd7Gs6am7cvokoU6PT/uncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P8AuncFA0U872NZ01N25fRJ3sazpqbty+iShTo9P+6dwUDRTzvY1nTU3bl9EnexrOmpu3L6JKFOj0/7p3BQNFPO9jWdNTduX0Sd7Gs6am7cvokoU6PT/uncFbCIi2F3RERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERTTVfoizE5JZJ3HueAtaYmOLXyvcMwDnDeyMDlG8ncCLFa81NMl4RiPwCwTMwyBDMR+AULRdEt0MwoC34PpfGYWl3lefCJ67rT41qxw2YEwiSlfyOheXM8Topcwy/FynrUDDyplnGjgR10B5qHZlDBJo4OHXd9VRyKRaX6H1eG+FIBJASA2oiByXO4NlYd8Lid2+4NwASdyjqsMCPDjMDoZBB1hTUGOyM3OYahERFlWVEUz0Q1eVOIQCoMzKWJxOyzxOkfI0btoGh7bMJuASd9r8LEyin1Qwf2tbO75KKKP+POomYtuUguLXPvFxABN/BRsW15WG4tc68agCeVFUiK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U0gTprZ/a+VWyiqbvnVnQUvYl9KnfOrOgpexL6VNIE6a2f2vlUDREWNceREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREX//2Q==\n", + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from IPython.display import YouTubeVideo\n", + "YouTubeVideo(\"Hwckt4J96dI\", width=\"60%\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "For example, while the above code to calculate the average of the even numbers in `[7, 11, 8, 5, 3, 12, 2, 6, 9, 10, 1, 4]` is correct, a Pythonista would rewrite it in a more \"Pythonic\" way and use the built-in [sum() ](https://docs.python.org/3/library/functions.html#sum) and [len() ](https://docs.python.org/3/library/functions.html#len) functions (cf., [Chapter 2 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_02_functions/00_content.ipynb#Built-in-Functions)) as well as a so-called **list comprehension** (cf., [Chapter 8 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_08_mfr/00_content.ipynb#List-Comprehensions)). Pythonic code runs faster in many cases and is less error-prone." + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "numbers = [7, 11, 8, 5, 3, 12, 2, 6, 9, 10, 1, 4]" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "evens = [n for n in numbers if n % 2 == 0] # use of a list comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[8, 12, 2, 6, 10, 4]" + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "evens" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "average = sum(evens) / len(evens) # use built-in functions" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "7.0" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "average" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "To get a rough overview of the mindset of a typical Python programmer, look at these rules, also known as the **Zen of Python**, that are deemed so important that they are included in every Python installation." + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The Zen of Python, by Tim Peters\n", + "\n", + "Beautiful is better than ugly.\n", + "Explicit is better than implicit.\n", + "Simple is better than complex.\n", + "Complex is better than complicated.\n", + "Flat is better than nested.\n", + "Sparse is better than dense.\n", + "Readability counts.\n", + "Special cases aren't special enough to break the rules.\n", + "Although practicality beats purity.\n", + "Errors should never pass silently.\n", + "Unless explicitly silenced.\n", + "In the face of ambiguity, refuse the temptation to guess.\n", + "There should be one-- and preferably only one --obvious way to do it.\n", + "Although that way may not be obvious at first unless you're Dutch.\n", + "Now is better than never.\n", + "Although never is often better than *right* now.\n", + "If the implementation is hard to explain, it's a bad idea.\n", + "If the implementation is easy to explain, it may be a good idea.\n", + "Namespaces are one honking great idea -- let's do more of those!\n" + ] + } + ], + "source": [ + "import this" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "### Jupyter Notebook Aspects" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "#### The Order of Code Cells is arbitrary" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "We can run the code cells in a Jupyter notebook in *any* arbitrary order.\n", + "\n", + "That means, for example, that a variable defined towards the bottom could accidentally be referenced at the top of the notebook. This happens quickly when we iteratively built a program and go back and forth between cells.\n", + "\n", + "As a good practice, it is recommended to click on \"Kernel\" > \"Restart Kernel and Run All Cells\" in the navigation bar once a notebook is finished. That restarts the Python process forgetting all **state** (i.e., all variables) and ensures that the notebook runs top to bottom without any errors the next time it is opened." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "#### Notebooks are linear" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "While this book is built with Jupyter notebooks, it is crucial to understand that \"real\" programs are almost never \"linear\" (i.e., top to bottom) sequences of instructions but instead may take many different **flows of execution**.\n", + "\n", + "At the same time, for a beginner's course, it is often easier to code linearly.\n", + "\n", + "In real data science projects, one would probably employ a mixed approach and put reusable code into so-called Python modules (i.e., *.py* files; cf., [Chapter 2 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_02_functions/00_content.ipynb#Local-Modules-and-Packages)) and then use Jupyter notebooks to build up a linear report or storyline for an analysis." + ] + } + ], + "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.8.6" + }, + "livereveal": { + "auto_select": "code", + "auto_select_fragment": true, + "scroll": true, + "theme": "serif" + }, + "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": { + "height": "calc(100% - 180px)", + "left": "10px", + "top": "150px", + "width": "303.333px" + }, + "toc_section_display": false, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From 263565f8a129f3240ad146c4c1d4e13f1ccf5aa6 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 12:26:31 +0200 Subject: [PATCH 07/14] Add initial version of chapter 01's exercises, part 1 --- README.md | 3 + chapter_01_elements/01_exercises.ipynb | 336 +++++++++++++++++++++++++ 2 files changed, 339 insertions(+) create mode 100644 chapter_01_elements/01_exercises.ipynb diff --git a/README.md b/README.md index de59194..51b053e 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,9 @@ Alternatively, the content can be viewed in a web browser ( [content 1 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/00_content.ipynb) [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/00_content.ipynb) + | + [exercises 1 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/01_exercises.ipynb) + [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/01_exercises.ipynb) ) diff --git a/chapter_01_elements/01_exercises.ipynb b/chapter_01_elements/01_exercises.ipynb new file mode 100644 index 0000000..6e057b5 --- /dev/null +++ b/chapter_01_elements/01_exercises.ipynb @@ -0,0 +1,336 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Run All*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *after* finishing the exercises to ensure that your solution runs top to bottom *without* any errors. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/01_exercises.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 1: Elements of a Program" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Coding Exercises" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The exercises below assume that you have read the first part of [Chapter 1 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/00_content.ipynb).\n", + "\n", + "The `...`'s in the code cells indicate where you need to fill in code snippets. The number of `...`'s within a code cell give you a rough idea of how many lines of code are needed to solve the task. You should not need to create any additional code cells for your final solution. However, you may want to use temporary code cells to try out some ideas." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### **Q1**: Printing Output" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q1.1**: *Concatenate* `greeting` and `audience` below with the `+` operator and print out the resulting message `\"Hello World\"` with only *one* call of the built-in [print() ](https://docs.python.org/3/library/functions.html#print) function!\n", + "\n", + "Hint: You may have to \"add\" a space character in between `greeting` and `audience`." + ] + }, + { + "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**: How is your answer to **Q1.1** an example of the concept of **operator overloading**?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q1.3**: Read the documentation on the built-in [print() ](https://docs.python.org/3/library/functions.html#print) function! How can you print the above message *without* concatenating `greeting` and `audience` first in *one* call of [print() ](https://docs.python.org/3/library/functions.html#print)?\n", + "\n", + "Hint: The `*objects` in the documentation implies that we can put several *expressions* (i.e., variables) separated by commas within the same call of the [print() ](https://docs.python.org/3/library/functions.html#print) function." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q1.4**: What does the `sep=\" \"` mean in the documentation on the built-in [print() ](https://docs.python.org/3/library/functions.html#print) function? Adjust and use it to print out the three names referenced by `first`, `second`, and `third` on *one* line separated by *commas* with only *one* call of the [print() ](https://docs.python.org/3/library/functions.html#print) function!" + ] + }, + { + "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.5**: Lastly, what does the `end=\"\\n\"` mean in the documentation? Adjust and use it within the `for`-loop to print the numbers `1` through `10` on *one* line with only *one* call of the [print() ](https://docs.python.org/3/library/functions.html#print) function!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### **Q2**: Simple `for`-loops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`for`-loops are extremely versatile in Python. That is different from many other programming languages.\n", + "\n", + "As shown in the first example in [Chapter 1 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/00_content.ipynb#Example:-Averaging-all-even-Numbers-in-a-List), we can create a `list` like `numbers` and loop over the numbers in it on a one-by-one basis." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numbers = [7, 11, 8, 5, 3, 12, 2, 6, 9, 10, 1, 4]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2.1**: Fill in the *condition* of the `if` statement such that only numbers divisible by `3` are printed! Adjust the call of the [print() ](https://docs.python.org/3/library/functions.html#print) function such that the `for`-loop prints out all the numbers on *one* line of output!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in numbers:\n", + " if ...:\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Instead of looping over an *existing* object referenced by a variable like `numbers`, we may also create a *new* object within the `for` statement and loop over it directly. For example, below we write out the `list` object as a *literal*.\n", + "\n", + "Generically, the objects contained in a `list` objects are referred to as its **elements**. We reflect that in the name of the *target* variable `element` that is assigned a different number in every iteration of the `for`-loop. While we could use *any* syntactically valid name, it is best to choose one that makes sense in the context (e.g., `number` in `numbers`).\n", + "\n", + "**Q2.2**: Fill in the condition of the `if` statement such that only numbers consisting of *one* digit are printed out! As before, print out all the numbers on *one* line of output!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for element in [7, 11, 8, 5, 3, 12, 2, 6, 9, 10, 1, 4]:\n", + " if ...:\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An easy way to loop over a `list` object in a sorted manner, is to wrap it with the built-in [sorted() ](https://docs.python.org/3/library/functions.html#sorted) function.\n", + "\n", + "**Q2.3**: Fill in the condition of the `if` statement such that only odd numbers are printed out! Put all the numbers on *one* line of output!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in sorted(numbers):\n", + " if ...:\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Whenever we want to loop over numbers representing a [series ](https://en.wikipedia.org/wiki/Series_%28mathematics%29) in the mathematical sense (i.e., a rule to calculate the next number from its predecessor), we may be able to use the [range() ](https://docs.python.org/3/library/functions.html#func-range) built-in.\n", + "\n", + "For example, to loop over the whole numbers from `0` to `9` (both including) in order, we could write them out in a `list` like below.\n", + "\n", + "**Q2.4**: Fill in the call to the [print() ](https://docs.python.org/3/library/functions.html#print) function such that all the numbers are printed on *one* line ouf output!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2.5**: Read the documentation on the [range() ](https://docs.python.org/3/library/functions.html#func-range) built-in! It may be used with either one, two, or three expressions \"passed\" in. What do `start`, `stop`, and `step` mean? Fill in the calls to [range() ](https://docs.python.org/3/library/functions.html#func-range) and [print() ](https://docs.python.org/3/library/functions.html#print) to mimic the output of **Q2.4**!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in range(...):\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2.6**: Fill in the calls to [range() ](https://docs.python.org/3/library/functions.html#func-range) and [print() ](https://docs.python.org/3/library/functions.html#print) to print out *all* numbers from `1` to `10` (both including)!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in range(...):\n", + " print(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2.7**: Fill in the calls to [range() ](https://docs.python.org/3/library/functions.html#func-range) and [print() ](https://docs.python.org/3/library/functions.html#print) to print out the *even* numbers from `1` to `10` (both including)! Do *not* use an `if` statement to accomplish this!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in range(...):\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.8.6" + }, + "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 +} From abeedd1265a5f88a4f5d2b9c78e370ca296fdcde Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 15:10:15 +0200 Subject: [PATCH 08/14] Add initial version of chapter 01, part 2 --- README.md | 3 + chapter_00_intro/00_content.ipynb | 2 +- chapter_01_elements/02_content.ipynb | 1665 ++++++++++++++++++++++++++ 3 files changed, 1669 insertions(+), 1 deletion(-) create mode 100644 chapter_01_elements/02_content.ipynb diff --git a/README.md b/README.md index 51b053e..ef3422e 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ Alternatively, the content can be viewed in a web browser | [exercises 1 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/01_exercises.ipynb) [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/01_exercises.ipynb) + | + [content 2 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/02_content.ipynb) + [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/02_content.ipynb) ) diff --git a/chapter_00_intro/00_content.ipynb b/chapter_00_intro/00_content.ipynb index fc6a255..219fbf3 100644 --- a/chapter_00_intro/00_content.ipynb +++ b/chapter_00_intro/00_content.ipynb @@ -496,7 +496,7 @@ } }, "source": [ - "The default Python implementation is written in the C language.\n", + "The default Python implementation is written in the C language and called CPython. This is also what the Anaconda Distribution uses.\n", "\n", "[C ](https://en.wikipedia.org/wiki/C_%28programming_language%29) and [C++ ](https://en.wikipedia.org/wiki/C%2B%2B) (cf., this [introduction](https://www.learncpp.com/)) are wide-spread and long-established (i.e., since the 1970s) programming languages employed in many mission-critical software systems (e.g., operating systems themselves, low latency databases and web servers, nuclear reactor control systems, airplanes, ...). They are fast, mainly because the programmer not only needs to come up with the **business logic** but also manage the computer's memory.\n", "\n", diff --git a/chapter_01_elements/02_content.ipynb b/chapter_01_elements/02_content.ipynb new file mode 100644 index 0000000..ae9459c --- /dev/null +++ b/chapter_01_elements/02_content.ipynb @@ -0,0 +1,1665 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Clear All Outputs*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *before* reading this notebook to reset its output. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/02_content.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Chapter 1: Elements of a Program (Part 2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this second part of Chapter 1, we look a bit closer into how the memory works and introduce a couple of \"theoretical\" terms." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Variables vs. Names vs. Identifiers vs. References" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "**Variables** are created with the **[assignment statement ](https://docs.python.org/3/reference/simple_stmts.html#assignment-statements)** `=`, which is *not* an operator because of its *side effect* of making a **[name ](https://docs.python.org/3/reference/lexical_analysis.html#identifiers)** reference an object in memory.\n", + "\n", + "We read the terms **variable**, **name**, and **identifier** used interchangebly in many Python-related texts. In this book, we adopt the following convention: First, we treat *name* and *identifier* as perfect synonyms but only use the term *name* in the text for clarity. Second, whereas *name* only refers to a string of letters, numbers, and some other symbols, a *variable* means the combination of a *name* and a *reference* to an object in memory." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "variable = 20.0" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "When used as a *literal*, a variable evaluates to the value of the object it references. Colloquially, we could say that `variable` evaluates to `20.0`, but this would not be an accurate description of what is going on in memory. We see some more colloquialisms in this section but should always relate this to what Python actually does in memory." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "20.0" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "variable" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "A variable may be **re-assigned** as often as we wish. Thereby, we could also assign an object of a *different* type. Because this is allowed, Python is said to be a **dynamically typed** language. On the contrary, a **statically typed** language like C also allows re-assignment but only with objects of the *same* type. This subtle distinction is one reason why Python is slower at execution than C: As it runs a program, it needs to figure out an object's type each time it is referenced." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "variable = 20" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "20" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "variable" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "If we want to re-assign a variable while referencing its \"old\" (i.e., current) object, we may also **update** it using a so-called **[augmented assignment statement ](https://docs.python.org/3/reference/simple_stmts.html#augmented-assignment-statements)** (i.e., *not* operator), as introduced with [PEP 203 ](https://www.python.org/dev/peps/pep-0203/): The currently mapped object is implicitly inserted as the first operand on the right-hand side." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "variable *= 4 # same as variable = variable * 4" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "80" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "variable" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "variable //= 2 # same as variable = variable // 2; \"//\" to retain the integer type" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "40" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "variable" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "variable += 2 # same as variable = variable + 2" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "42" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "variable" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Variables are **[dereferenced ](https://docs.python.org/3/reference/simple_stmts.html#the-del-statement)** (i.e., \"deleted\") with the `del` statement. This does *not* delete the object a variable references but merely removes the variable's name from the \"global list of all names.\"" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "42" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "variable" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "del variable" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "If we refer to an unknown name, a *runtime* error occurs, namely a `NameError`. The `Name` in `NameError` gives a hint why we choose the term *name* over *identifier* above: Python uses it more often in its error messages." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'variable' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mvariable\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'variable' is not defined" + ] + } + ], + "source": [ + "variable" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Some variables magically exist when a Python process is started or are added by Jupyter. We may safely ignore the former until [Chapter 11 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_11_classes/00_content.ipynb) and the latter for good." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'__main__'" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "__name__" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "To see all defined names, the built-in function [dir() ](https://docs.python.org/3/library/functions.html#dir) is helpful." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['In',\n", + " 'Out',\n", + " '_',\n", + " '_10',\n", + " '_11',\n", + " '_14',\n", + " '_2',\n", + " '_4',\n", + " '_6',\n", + " '_8',\n", + " '__',\n", + " '___',\n", + " '__builtin__',\n", + " '__builtins__',\n", + " '__doc__',\n", + " '__loader__',\n", + " '__name__',\n", + " '__package__',\n", + " '__spec__',\n", + " '_dh',\n", + " '_i',\n", + " '_i1',\n", + " '_i10',\n", + " '_i11',\n", + " '_i12',\n", + " '_i13',\n", + " '_i14',\n", + " '_i15',\n", + " '_i2',\n", + " '_i3',\n", + " '_i4',\n", + " '_i5',\n", + " '_i6',\n", + " '_i7',\n", + " '_i8',\n", + " '_i9',\n", + " '_ih',\n", + " '_ii',\n", + " '_iii',\n", + " '_oh',\n", + " 'exit',\n", + " 'get_ipython',\n", + " 'quit',\n", + " 'register_readline_completion',\n", + " 'sys']" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dir()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Naming Conventions" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "[Phil Karlton](https://skeptics.stackexchange.com/questions/19836/has-phil-karlton-ever-said-there-are-only-two-hard-things-in-computer-science) famously noted during his time at [Netscape ](https://en.wikipedia.org/wiki/Netscape):\n", + "\n", + "> \"There are *two* hard problems in computer science: *naming things* and *cache invalidation* ... and *off-by-one* errors.\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Variable names may contain upper and lower case letters, numbers, and underscores (i.e., `_`) and be as long as we want them to be. However, they must not begin with a number. Also, they must not be any of Python's built-in **[keywords ](https://docs.python.org/3/reference/lexical_analysis.html#keywords)** like `for` or `if`.\n", + "\n", + "Variable names should be chosen such that they do not need any more documentation and are self-explanatory. A widespread convention is to use so-called **[snake\\_case ](https://en.wikipedia.org/wiki/Snake_case)**: Keep everything lowercase and use underscores to separate words.\n", + "\n", + "See this [link ](https://en.wikipedia.org/wiki/Naming_convention_%28programming%29#Python_and_Ruby) for a comparison of different naming conventions." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "#### Good examples" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "pi = 3.14" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "answer_to_everything = 42" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "my_name = \"Alexander\"" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "work_address = \"WHU, Burgplatz 2, Vallendar\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "#### Bad examples" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "PI = 3.14 # unless used as a \"global\" constant" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "answerToEverything = 42 # this is a style used in languages like Java" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "name = \"Alexander\" # name of what?" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "cannot assign to operator (, line 1)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m address@work = \"WHU, Burgplatz 2, Vallendar\"\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m cannot assign to operator\n" + ] + } + ], + "source": [ + "address@work = \"WHU, Burgplatz 2, Vallendar\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "If a variable name collides with a built-in name, we add a trailing underscore." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "type_ = \"student\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Variables with leading and trailing double underscores, referred to as **dunder** in Python jargon, are used for built-in functionalities and to implement object-oriented features as we see in [Chapter 11 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_11_classes/00_content.ipynb). We must *not* use this style for variables!" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'__main__'" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "__name__" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Who am I? And how many?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "It is *crucial* to understand that *several* variables may reference the *same* object in memory. Not having this in mind may lead to many hard to track down bugs.\n", + "\n", + "Let's make `b` reference whatever object `a` is referencing." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "a = 42" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "b = a" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "42" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "For \"simple\" types like `int` or `float` this never causes troubles.\n", + "\n", + "Let's \"change the value\" of `a`. To be precise, let's create a *new* `87` object and make `a` reference it." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "a = 87" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "87" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "`b` \"is still the same\" as before. To be precise, `b` still references the *same object* as before." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "42" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "However, if a variable references an object of a more \"complex\" type (e.g., `list`), predicting the outcome of a code snippet may be unintuitive for a beginner." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "x = [1, 2, 3]" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "list" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(x)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "y = x" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3]" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Let's change the first element of `x`.\n", + "\n", + "[Chapter 7 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_07_sequences/00_content.ipynb#The-list-Type) discusses lists in more depth. For now, let's view a `list` object as some sort of **container** that holds an arbitrary number of references to other objects and treat the brackets `[]` attached to it as yet another operator, namely the **indexing operator**. So, `x[0]` instructs Python to first follow the reference from the global list of all names to the `x` object. Then, it follows the first reference it finds there to the `1` object we put in the list. The indexing operator must be an operator as we merely *read* the first element and do not change anything in memory permanently.\n", + "\n", + "Python **begins counting at 0**. This is not the case for many other languages, for example, [MATLAB ](https://en.wikipedia.org/wiki/MATLAB), [R ](https://en.wikipedia.org/wiki/R_%28programming_language%29), or [Stata ](https://en.wikipedia.org/wiki/Stata). To understand why this makes sense, see this short [note](https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html) by one of the all-time greats in computer science, the late [Edsger Dijkstra ](https://en.wikipedia.org/wiki/Edsger_W._Dijkstra)." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "To change the first entry in the list, we use the assignment statement `=` again. Here, this does *not* create a *new* variable, nor overwrite an existing one, but only changes the object referenced as the first element in `x`. As we only change parts of the `x` object, we say that we **mutate** its **state**. To use the bag analogy from above, we keep the same bag but \"flip\" some of the $0$s into $1$s and some of the $1$s into $0$s." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "x[0] = 99" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[99, 2, 3]" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The changes made to the object `x` is referencing can also be seen through the `y` variable!" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[99, 2, 3]" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The difference in behavior illustrated in this sub-section has to do with the fact that `int` and `float` objects are **immutable** types while `list` objects are **mutable**.\n", + "\n", + "In the first case, an object cannot be changed \"in place\" once it is created in memory. When we assigned `87` to the already existing `a`, we did *not* change the $0$s and $1$s in the object `a` referenced before the assignment but created a new `int` object and made `a` reference it while the `b` variable is *not* affected.\n", + "\n", + "In the second case, `x[0] = 99` creates a *new* `int` object `99` and merely changes the first reference in the `x` list.\n", + "\n", + "In general, the assignment statement creates a new name and makes it reference whatever object is on the right-hand side *iff* the left-hand side is a *pure* name (i.e., it contains no operators like the indexing operator in the example). Otherwise, it *mutates* an already existing object. And, we must always expect that the latter may have more than one variable referencing it.\n", + "\n", + "Visualizing what is going on in memory with a tool like [PythonTutor ](http://pythontutor.com/visualize.html#code=x%20%3D%20%5B1,%202,%203%5D%0Ay%20%3D%20x%0Ax%5B0%5D%20%3D%2099%0Aprint%28y%5B0%5D%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) may be helpful for a beginner." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## How Python reads \"Commands\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we saw in the previous `list` example, it is important to understand in what order Python executes the \"commands\" (= not an officially used term) we give it. In this last section of the chapter, we introduce a classification scheme and look at its implications." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Expressions" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "An **[expression ](https://docs.python.org/3/reference/expressions.html)** is any syntactically correct *combination* of *variables* and *literals* with *operators* that **evaluates** (i.e., \"becomes\") to an object. That object may already exist *before* the expression is parsed or created as a result thereof. The point is that *after* the expression is parsed, Python returns a reference to this object that may be used for further processing.\n", + "\n", + "In simple words, anything that may be used on the *right-hand* side of an assignment statement without creating a `SyntaxError` is an expression.\n", + "\n", + "What we have said about *individual* operators before, namely that they have *no* permanent side effects in memory, actually belongs here, to begin with: The absence of any *permanent* side effects is the characteristic property of expressions, and all the code cells in the \"*(Arithmetic) Operators*\" section in the [first part ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/00_content.ipynb#%28Arithmetic%29-Operators) of this chapter are examples of expressions.\n", + "\n", + "The simplest possible expressions contain only one variable or literal. The output below a code cell is Jupyter's way of returning the reference to the object to us!\n", + "\n", + "Whereas `a` evaluates to the *existing* `87` object, ..." + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "87" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... parsing the literal `42` creates a *new* `int` object and returns a reference to it (Note: for optimization reasons, the CPython implementation may already have a `42` object in memory)." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "42" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "42" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "For sure, we need to include operators to achieve something useful. Here, Python takes the existing `a` object, creates a new `42` object, creates the resulting `45` object, and returns a reference to that." + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "45" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a - 42" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The definition of an expression is **recursive**. So, the sub-expression `a - 42` is combined with the literal `9` by the operator `//` to form the full expression `(a - 42) // 9`." + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "5" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(a - 42) // 9" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Below, the variable `x` is combined with the literal `2` by the indexing operator `[]`. The resulting expression evaluates to the third element in the `x` list." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x[2]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "When not used as a delimiter, parentheses also constitute an operator, namely the **call operator** `()`. We saw this syntax before when we called built-in functions and methods." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "104" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sum(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Statements" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "A **[statement ](https://docs.python.org/3/reference/simple_stmts.html)** is any *single* command Python understands.\n", + "\n", + "So, what we mean with statement is a [strict superset ](https://en.wikipedia.org/wiki/Subset) of what we mean with expression: All expressions are statements, but some statements are *not* expressions. That implies that all code cells in the previous \"*Expressions*\" section are also examples of statements.\n", + "\n", + "Unfortunately, many texts on Python use the two terms as mutually exclusive concepts by saying that a statement (always) *changes* the *state of a program* with a permanent *side effect* in memory (e.g., by creating a variable) whereas an expression does not. That is not an accurate way of distinguishing the two in all cases!\n", + "\n", + "So, often, the term statement is used in the meaning of \"a statement that is *not* an expression.\" We can identify such statements easily in Jupyter as the correspoding code cells have *no* output below them.\n", + "\n", + "While many statements, for example `=` and `del`, indeed have *permanent* side effects, ..." + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "a = 21 * 2" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "del a" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "... calling the built-in [print() ](https://docs.python.org/3/library/functions.html#print) function does *neither* change the memory *nor* evaluate to an object (disregarding the `None` object explained in [Chapter 2 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_02_functions/00_content.ipynb#Function-Definitions)). We could view changing the computer's screen as a side effect but this is outside of Python's memory!\n", + "\n", + "Also, the cell below has *no* output! It only looks like it does as Jupyter redirects whatever [print() ](https://docs.python.org/3/library/functions.html#print) writes to the \"screen\" to below a cell. We see a difference to the expressions above in that there are no brackets `[...]` next to the output showing the execution count number." + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Don't I change the state of the computer's display?\n" + ] + } + ], + "source": [ + "print(\"Don't I change the state of the computer's display?\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Logical vs. Physical Lines" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "How many lines of code does the next cell constitute?" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The answer is: 42\n" + ] + } + ], + "source": [ + "result = 21 * 2; print(\"The answer is:\", result)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The answer depends on how we are counting. If we count the number of lines of written source code, the answer is *one*. This gives us the number of **physical lines**. On the contrary, if we count the number of statements separated by the `;`, the answer is *two*. This gives us the number of **logical lines**.\n", + "\n", + "While physical lines are what we, the humans, see, logical lines are how computers read. To align the two ways, it is a best practice to not write more than one logical lines on a single physical one. So, from Python's point of view, the cells above and below are the same. More importantly, the one above is *not* somehow \"magically\" faster." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The answer is: 42\n" + ] + } + ], + "source": [ + "result = 21 * 2\n", + "print(\"The answer is:\", result)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is also possible to write a single logical line over several physical ones. The cell below is yet another physical representation of the same *two* logical lines. Any pair of delimiters, like `(` and `)` below, can be used to \"format\" the code in between with whitespace. The style guides mentioned before should still be taken into account (i.e., indent with 4 spaces)." + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The answer is: 42\n" + ] + } + ], + "source": [ + "result = 21 * 2\n", + "print(\n", + " \"The answer is:\",\n", + " result\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Another situation, in which several physical lines are treated as a logical one, is with so-called **[compound statements ](https://docs.python.org/3/reference/compound_stmts.html)**. In contrast to simple statements like `=` and `del` above, the purpose of compound statements is to group other statements.\n", + "\n", + "We have seen two examples of compound statements already: `for` and `if`. They both consist of a **header** line ending with a `:` and an indented **(code) block** spanning an arbitrary number of logical lines.\n", + "\n", + "In the example, the first logical line spans the entire cell, the second logical line contains all physical lines except the first, and the third and fourth logical lines are just the third and fourth physical lines, respectively." + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2 -> 4\n" + ] + } + ], + "source": [ + "for number in [1, 2, 3]:\n", + " if number % 2 == 0:\n", + " double = 2 * number \n", + " print(number, \"->\", double)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Comments" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "A comment is a physical line that is *not* a logical line.\n", + "\n", + "We use the `#` symbol to write comments in plain text right into the code. Anything after the `#` until the end of the physical line is ignored by Python.\n", + "\n", + "As a good practice, comments should *not* describe *what* happens. This should be evident by reading the code. Otherwise, it is most likely badly written code. Rather, comments should describe *why* something happens.\n", + "\n", + "Comments may be added either at the end of a line of code, by convention separated with two spaces, or on a line on their own." + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "distance = 891 # in meters\n", + "elapsed_time = 93 # in seconds\n", + "\n", + "# Calculate the speed in km/h.\n", + "speed = 3.6 * distance / elapsed_time" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "But let's think wisely if we need to use a comment.\n", + "The second cell is a lot more Pythonic." + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "seconds = 365 * 24 * 60 * 60 # = seconds in the year" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "seconds_per_year = 365 * 24 * 60 * 60" + ] + } + ], + "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.8.6" + }, + "livereveal": { + "auto_select": "code", + "auto_select_fragment": true, + "scroll": true, + "theme": "serif" + }, + "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": { + "height": "calc(100% - 180px)", + "left": "10px", + "top": "150px", + "width": "303.333px" + }, + "toc_section_display": false, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From 5163c34d534e33d46e2bddcabe13a220f0118a5f Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 15:19:55 +0200 Subject: [PATCH 09/14] Add initial version of chapter 01's exercises, part 2 --- README.md | 3 + chapter_01_elements/03_exercises.ipynb | 219 +++++++++++++++++++++++++ 2 files changed, 222 insertions(+) create mode 100644 chapter_01_elements/03_exercises.ipynb diff --git a/README.md b/README.md index ef3422e..07873b2 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,9 @@ Alternatively, the content can be viewed in a web browser | [content 2 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/02_content.ipynb) [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/02_content.ipynb) + | + [exercises 2 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/03_exercises.ipynb) + [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/03_exercises.ipynb) ) diff --git a/chapter_01_elements/03_exercises.ipynb b/chapter_01_elements/03_exercises.ipynb new file mode 100644 index 0000000..d9d0bbf --- /dev/null +++ b/chapter_01_elements/03_exercises.ipynb @@ -0,0 +1,219 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Run All*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *after* finishing the exercises to ensure that your solution runs top to bottom *without* any errors. If you cannot run this file on your machine, you may want to open it [in the cloud ](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/03_exercises.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 1: Elements of a Program (Part 2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Coding Exercises" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The exercises below assume that you have read the second part of [Chapter 1 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/02_content.ipynb).\n", + "\n", + "The `...`'s in the code cells indicate where you need to fill in code snippets. The number of `...`'s within a code cell give you a rough idea of how many lines of code are needed to solve the task. You should not need to create any additional code cells for your final solution. However, you may want to use temporary code cells to try out some ideas." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Python as a Calculator" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The [volume of a sphere ](https://en.wikipedia.org/wiki/Sphere) is defined as $\\frac{4}{3} * \\pi * r^3$.\n", + "\n", + "**Q1**: Calculate it for `r = 2.88` and approximate $\\pi$ with `pi = 3.14`!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pi = 3.14\n", + "r = 2.88" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "While Python may be used as a calculator, it behaves a bit differently compared to calculator apps that phones or computers come with and that we are accustomed to.\n", + "\n", + "A major difference is that Python \"forgets\" intermediate results that are not assigned to variables. On the contrary, the calculators we work with outside of programming always keep the last result and allow us to use it as the first input for the next calculation.\n", + "\n", + "One way to keep on working with intermediate results in Python is to write the entire calculation as just *one* big expression that is composed of many sub-expressions representing the individual steps in our overall calculation.\n", + "\n", + "**Q2.1**: Given `a` and `b` like below, subtract the smaller `a` from the larger `b`, divide the difference by `9`, and raise the result to the power of `2`! Use operators that preserve the `int` type of the final result! The entire calculations *must* be placed within *one* code cell.\n", + "\n", + "Hint: You may need to group sub-expressions with parentheses `(` and `)`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a = 42\n", + "b = 87" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The code cell below contains nothing but a single underscore `_`. In both, a Python command-line prompt and Jupyter notebooks, the variable `_` is automatically updated and always references the object to which the *last* expression executed evaluated to.\n", + "\n", + "**Q2.2**: Execute the code cell below! It should evaluate to the *same* result as the previous code cell (i.e., your answer to **Q2.1** assuming you go through this notebook in order)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2.3**: Implement the same overall calculation as in your answer to **Q2.1** in several independent steps (i.e., code cells)! Use only *one* operator per code cell!\n", + "\n", + "Hint: You should need *two* more code cells after the `b - a` one immediately below. If you *need* to use parentheses, you must be doing something wrong." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "b - a" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_ ..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "_ ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q3.1**: When answering the questions above, you should have used only **expressions** in the code cells. What are expressions syntactically?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q3.2**: The code cells that provide the numbers to work with contain **statements** that are *not* expressions. What are statements? How are they different from expressions?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + } + ], + "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.8.6" + }, + "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 +} From 777da3568d7a539023cf909e1113f0c7558e2dd3 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 15:24:21 +0200 Subject: [PATCH 10/14] Add initial version of chapter 01's summary --- README.md | 2 + chapter_01_elements/04_summary.ipynb | 154 +++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 chapter_01_elements/04_summary.ipynb diff --git a/README.md b/README.md index 07873b2..425e21f 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,8 @@ Alternatively, the content can be viewed in a web browser | [exercises 2 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/03_exercises.ipynb) [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/03_exercises.ipynb) + | + [summary ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/04_summary.ipynb) ) diff --git a/chapter_01_elements/04_summary.ipynb b/chapter_01_elements/04_summary.ipynb new file mode 100644 index 0000000..9f52d19 --- /dev/null +++ b/chapter_01_elements/04_summary.ipynb @@ -0,0 +1,154 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "\n", + "# Chapter 1: Elements of a Program" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "## TL;DR" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "We end each chapter with a summary of the main points (i.e., **TL;DR** = \"too long; didn't read\"). The essence in this first chapter is that just as a sentence in a real language like English may be decomposed into its parts (e.g., subject, predicate, and objects), the same may be done with programming languages.\n", + "\n", + "- program\n", + " - **sequence** of **instructions** that specify how to perform a computation (= a \"recipe\")\n", + " - a \"black box\" that processes **inputs** and transforms them into meaningful **outputs** in a *deterministic* way\n", + " - conceptually similar to a mathematical function $f$ that maps some input $x$ to an output $y = f(x)$\n", + "\n", + "\n", + "- input (examples)\n", + " - data from a CSV file\n", + " - text entered on a command line\n", + " - data obtained from a database\n", + " - etc.\n", + "\n", + "\n", + "- output (examples)\n", + " - result of a computation (e.g., statistical summary of a sample dataset)\n", + " - a \"side effect\" (e.g., a transformation of raw input data into cleaned data)\n", + " - a physical \"behavior\" (e.g., a robot moving or a document printed)\n", + " - etc.\n", + "\n", + "\n", + "- objects\n", + " - distinct and well-contained areas/parts of the memory that hold the actual data\n", + " - the concept by which Python manages the memory for us\n", + " - can be classified into objects of the same **type** (i.e., same abstract \"structure\" but different concrete data)\n", + " - built-in objects (incl. **literals**) vs. user-defined objects (cf., [Chapter 11 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_11_classes/00_content.ipynb))\n", + " - e.g., `1`, `1.0`, and `\"one\"` are three different objects of distinct types that are also literals (i.e., by the way we type them into the command line Python knows what the value and type are)\n", + "\n", + "\n", + "- variables\n", + " - storage of intermediate **state**\n", + " - are **names** referencing **objects** in **memory**\n", + " - e.g., `x = 1` creates the variable `x` that references the object `1`\n", + "\n", + "\n", + "- operators\n", + " - special built-in symbols that perform operations with objects in memory\n", + " - usually, operate with one or two objects\n", + " - e.g., addition `+`, subtraction `-`, multiplication `*`, and division `/` all take two objects, whereas the negation `-` only takes one\n", + "\n", + "\n", + "- expressions\n", + " - **combinations** of **variables** (incl. **literals**) and **operators**\n", + " - do *not* change the involved objects/state of the program\n", + " - evaluate to a **value** (i.e., the \"result\" of the expression, usually a new object)\n", + " - e.g., `x + 2` evaluates to the (new) object `3` and `1 - 1.0` to `0.0`\n", + "\n", + "\n", + "- statements\n", + " - instructions that **\"do\" something** and **have side effects** in memory\n", + " - (re-)assign names to (different) objects, *change* an existing object *in place*, or, more conceptually, *change* the state of the program\n", + " - usually, work with expressions\n", + " - e.g., the assignment statement `=` makes a name reference an object\n", + "\n", + "\n", + "- comments\n", + " - **prose** supporting a **human's understanding** of the program\n", + " - ignored by Python\n", + "\n", + "\n", + "- functions (cf., [Chapter 2 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_02_functions/00_content.ipynb))\n", + " - named sequences of instructions\n", + " - the smaller parts in a larger program\n", + " - make a program more modular and thus easier to understand\n", + " - include [built-in functions ](https://docs.python.org/3/library/functions.html) like [print() ](https://docs.python.org/3/library/functions.html#print), [sum() ](https://docs.python.org/3/library/functions.html#sum), or [len() ](https://docs.python.org/3/library/functions.html#len)\n", + "\n", + "\n", + "- flow control (cf., [Chapter 3 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_03_conditionals/00_content.ipynb) and [Chapter 4 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_04_iteration/00_content.ipynb))\n", + " - expression of **business logic** or an **algorithm**\n", + " - conditional execution of parts of a program (e.g., `if` statements)\n", + " - repetitive execution of parts of a program (e.g., `for`-loops)" + ] + } + ], + "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.8.6" + }, + "livereveal": { + "auto_select": "code", + "auto_select_fragment": true, + "scroll": true, + "theme": "serif" + }, + "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": { + "height": "calc(100% - 180px)", + "left": "10px", + "top": "150px", + "width": "303.333px" + }, + "toc_section_display": false, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From 6fb318d13aaae4c0c454bffa0d2297a9bc803f62 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 15:25:22 +0200 Subject: [PATCH 11/14] Add initial version of chapter 01's review --- README.md | 2 + chapter_01_elements/05_review.ipynb | 222 ++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 chapter_01_elements/05_review.ipynb diff --git a/README.md b/README.md index 425e21f..d090fdb 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ Alternatively, the content can be viewed in a web browser [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/03_exercises.ipynb) | [summary ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/04_summary.ipynb) + | + [review ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/05_review.ipynb) ) diff --git a/chapter_01_elements/05_review.ipynb b/chapter_01_elements/05_review.ipynb new file mode 100644 index 0000000..d8ec024 --- /dev/null +++ b/chapter_01_elements/05_review.ipynb @@ -0,0 +1,222 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 1: Elements of a Program" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Content Review" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The questions below assume that you have read the [first ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/00_content.ipynb) and the [second ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/02_content.ipynb) part of Chapter 1.\n", + "\n", + "Be concise in your answers! Most questions can be answered in *one* sentence." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Essay Questions " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q1**: Elaborate on how **modulo division** might be a handy operation to know!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2**: What is a **dynamically typed** language? How does it differ from a **statically typed** language? What does that mean for Python?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q3**: Why is it useful to start counting at $0$?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q4**: What is **operator overloading**?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q5**: What are the basic **naming conventions** for variables? What happens if a name collides with one of Python's [keywords ](https://docs.python.org/3/reference/lexical_analysis.html#keywords)?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q6**: Advocates of the [functional programming ](https://en.wikipedia.org/wiki/Functional_programming) paradigm suggest not to use **mutable** data types in a program. What are the advantages of that approach? What might be a downside?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + }, + { + "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**: \"**dunder**\" refers to a group of Australian (i.e., \"down under\") geeks that work on core Python." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q8**: The **Zen of Python** talks about Indian genius programmers." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q9**: When NASA famously converted some measurements to the wrong unit and lost a Mars satellite in 1999 (cf., [source](https://www.wired.com/2010/11/1110mars-climate-observer-report/)), this is an example of a so-called **runtime error**." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q10**: [PEP 8 ](https://www.python.org/dev/peps/pep-0008/) suggests that developers use **8 spaces** per level of indentation." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + } + ], + "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.8.6" + }, + "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 +} From ba9addd56272790b2599dbb59bbe0837d1fd3917 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 15:26:18 +0200 Subject: [PATCH 12/14] Chapter reviews are not interactive --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index d090fdb..ff4e0b7 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ Alternatively, the content can be viewed in a web browser [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_00_intro/01_exercises.ipynb) | [review ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_00_intro/02_review.ipynb) - [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_00_intro/02_review.ipynb) ) - **Part A: Expressing Logic** - *Chapter 1*: Elements of a Program From 5b6fd7122fc8625c725ca71f17957d0caf3a9416 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 15:28:02 +0200 Subject: [PATCH 13/14] Add initial version of chapter 01's further resources --- README.md | 3 + chapter_01_elements/06_resources.ipynb | 120 +++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 chapter_01_elements/06_resources.ipynb diff --git a/README.md b/README.md index ff4e0b7..0c4e26d 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,9 @@ Alternatively, the content can be viewed in a web browser [summary ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/04_summary.ipynb) | [review ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/05_review.ipynb) + | + [resources ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/chapter_01_elements/06_resources.ipynb) + [](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/chapter_01_elements/06_resources.ipynb) ) diff --git a/chapter_01_elements/06_resources.ipynb b/chapter_01_elements/06_resources.ipynb new file mode 100644 index 0000000..bdc2e29 --- /dev/null +++ b/chapter_01_elements/06_resources.ipynb @@ -0,0 +1,120 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "\n", + "# Chapter 1: Elements of a Program" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "## Further Resources" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "This PyCon 2015 talk by [Ned Batchelder](https://nedbatchelder.com/), a well-known Pythonista and the organizer of the [Python User Group](https://www.meetup.com/bostonpython/) in Boston, summarizes all situations where some sort of assignment is done in Python and, thus, reviews how *variables are just names referencing objects*. The content is intermediate, and, thus, it might be worthwhile to come back to this talk at a later point in time. However, the contents should be known by everyone claiming to be proficient in Python." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "image/jpeg": "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\n", + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from IPython.display import YouTubeVideo\n", + "YouTubeVideo(\"_AEJHKGk9ns\", width=\"60%\")" + ] + } + ], + "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.8.6" + }, + "livereveal": { + "auto_select": "code", + "auto_select_fragment": true, + "scroll": true, + "theme": "serif" + }, + "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": { + "height": "calc(100% - 180px)", + "left": "10px", + "top": "150px", + "width": "303.333px" + }, + "toc_section_display": false, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From 138bc12945589801cbfe22ca1f28b48b659f4814 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 13 Oct 2020 15:36:35 +0200 Subject: [PATCH 14/14] Streamline slides --- chapter_01_elements/02_content.ipynb | 80 +++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/chapter_01_elements/02_content.ipynb b/chapter_01_elements/02_content.ipynb index ae9459c..ea72a59 100644 --- a/chapter_01_elements/02_content.ipynb +++ b/chapter_01_elements/02_content.ipynb @@ -24,7 +24,11 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, "source": [ "In this second part of Chapter 1, we look a bit closer into how the memory works and introduce a couple of \"theoretical\" terms." ] @@ -1089,14 +1093,22 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "## How Python reads \"Commands\"" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, "source": [ "As we saw in the previous `list` example, it is important to understand in what order Python executes the \"commands\" (= not an officially used term) we give it. In this last section of the chapter, we introduce a classification scheme and look at its implications." ] @@ -1157,7 +1169,11 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, "source": [ "... parsing the literal `42` creates a *new* `int` object and returns a reference to it (Note: for optimization reasons, the CPython implementation may already have a `42` object in memory)." ] @@ -1400,7 +1416,7 @@ "execution_count": 48, "metadata": { "slideshow": { - "slide_type": "skip" + "slide_type": "fragment" } }, "outputs": [ @@ -1418,14 +1434,22 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "source": [ "### Logical vs. Physical Lines" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, "source": [ "How many lines of code does the next cell constitute?" ] @@ -1433,7 +1457,11 @@ { "cell_type": "code", "execution_count": 49, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "outputs": [ { "name": "stdout", @@ -1449,7 +1477,11 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, "source": [ "The answer depends on how we are counting. If we count the number of lines of written source code, the answer is *one*. This gives us the number of **physical lines**. On the contrary, if we count the number of statements separated by the `;`, the answer is *two*. This gives us the number of **logical lines**.\n", "\n", @@ -1459,7 +1491,11 @@ { "cell_type": "code", "execution_count": 50, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, "outputs": [ { "name": "stdout", @@ -1476,7 +1512,11 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, "source": [ "It is also possible to write a single logical line over several physical ones. The cell below is yet another physical representation of the same *two* logical lines. Any pair of delimiters, like `(` and `)` below, can be used to \"format\" the code in between with whitespace. The style guides mentioned before should still be taken into account (i.e., indent with 4 spaces)." ] @@ -1484,7 +1524,11 @@ { "cell_type": "code", "execution_count": 51, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, "outputs": [ { "name": "stdout", @@ -1504,7 +1548,11 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, "source": [ "Another situation, in which several physical lines are treated as a logical one, is with so-called **[compound statements ](https://docs.python.org/3/reference/compound_stmts.html)**. In contrast to simple statements like `=` and `del` above, the purpose of compound statements is to group other statements.\n", "\n", @@ -1516,7 +1564,11 @@ { "cell_type": "code", "execution_count": 52, - "metadata": {}, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, "outputs": [ { "name": "stdout",