From 88bcb3861a3ff27e10b7adfdf15d4d1afbad19e3 Mon Sep 17 00:00:00 2001 From: b4d Date: Tue, 20 Mar 2018 08:41:08 +0100 Subject: [PATCH 01/59] Added MacPorts install info. --- chapters/installation.tex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chapters/installation.tex b/chapters/installation.tex index de6a143..f91aab7 100644 --- a/chapters/installation.tex +++ b/chapters/installation.tex @@ -42,7 +42,8 @@ \section{Installing on Windows} \section{Installing on macOS} -You can download the latest macOS binary releases from \url{https://www.python.org/downloads/mac-osx/}. Make sure you download the latest Python 3 release (3.6.4 at the time of writing). You can also use Homebrew, a package manager for macOS (\url{https://brew.sh/}). To install the latest Python 3 release with Homebrew, just do "\texttt{brew install python3}" on your terminal. +You can download the latest macOS binary releases from \url{https://www.python.org/downloads/mac-osx/}. Make sure you download the latest Python 3 release (3.6.4 at the time of writing). You can also use Homebrew, a package manager for macOS (\url{https://brew.sh/}). To install the latest Python 3 release with Homebrew, just do "\texttt{brew install python3}" on your terminal. Another option is to use MacPorts package manager (\url{https://www.macports.org/}) and command "\texttt{port install python36}". + \begin{figure}[H] \centering From b0a27b7dae5cfbebc28358174b785ac3c0e0fbd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Tue, 20 Mar 2018 12:04:30 +0000 Subject: [PATCH 02/59] Change book title --- .gitignore | 3 +++ Makefile | 12 ++++-------- README.md | 11 ++++++++--- chapters/introduction.tex | 6 +++--- full-speed-python.tex | 4 ++-- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index b001411..8a35989 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# macOS +.DS_Store + # Latex *.aux *.log diff --git a/Makefile b/Makefile index dacc7fb..09e20dd 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,13 @@ all: epub pdf epub: - pandoc -o full-speed-python.epub \ - full-speed-python.tex \ - chapters/installation.tex \ - chapters/basic-datatypes.tex \ - chapters/functions.tex \ - chapters/loops.tex \ - chapters/dictionaries.tex \ - chapters/classes.tex \ + pandoc -o full-speed-python.epub full-speed-python.tex pdf: pdflatex full-speed-python.tex + pdflatex full-speed-python.tex clean: rm *.epub *.pdf + rm chapters/*.aux + rm *.aux *.log *.out *.toc diff --git a/README.md b/README.md index 04b4638..415455e 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,14 @@ -# At full speed with Python +# Getting up to speed with Python + +Pdf and epub files can be downloaded from: https://github.com/joaoventura/full-speed-python/releases/ This book aims to teach the basics of the python programming language using a practical approach. Its method is quite basic though: after a very simple introduction to each topic, the reader is invited to learn by solving the proposed exercises. -These exercises have been used extensively in my web development and distributed computing classes at the Superior School of Technology of Setúbal. With these exercises, most students are at full speed with Python in less than a month. In fact, students of the distributed computing course, taught in the second year of the software engineering degree, become familiar with Python's syntax in two weeks and are able to implement a distributed client-server application with sockets in the third week. +These exercises have been used extensively in my web development and distributed computing classes at the Superior School of Technology of Setúbal. With these exercises, most students are up to speed with Python in less than a month. In fact, students of the distributed computing course, taught in the second year of the software engineering degree, become familiar with Python's syntax in two weeks and are able to implement a distributed client-server application with sockets in the third week. This book is made available in github (https://github.com/joaoventura/full-speed-python) so I appreciate any pull requests to correct misspellings or to suggest new exercises or clarification of the current content. -The generated files (pdf and epub) can be found at https://github.com/joaoventura/full-speed-python/releases/. + +## Building + +The pdf file is built with pdflatex, so you may need to download a latex distribution. The epub file is built with [pandoc](http://pandoc.org/). diff --git a/chapters/introduction.tex b/chapters/introduction.tex index f95b087..ce1a4c7 100644 --- a/chapters/introduction.tex +++ b/chapters/introduction.tex @@ -2,14 +2,14 @@ \chapter{Introduction}\label{introduction} This book aims to teach the basics of the Python programming language using a practical approach. Its method is quite basic though: after a very simple introduction to each topic, the reader is invited to learn by solving the proposed exercises. -These exercises have been used extensively in my web development and distributed computing classes at the Superior School of Technology of Setúbal. With these exercises, most students are at full speed with Python in less than a month. In fact, students of the distributed computing course, taught in the second year of the software engineering degree, become familiar with Python's syntax in two weeks and are able to implement a distributed client-server application with sockets in the third week. +These exercises have been used extensively in my web development and distributed computing classes at the Superior School of Technology of Setúbal. With these exercises, most students are up to speed with Python in less than a month. In fact, students of the distributed computing course, taught in the second year of the software engineering degree, become familiar with Python's syntax in two weeks and are able to implement a distributed client-server application with sockets in the third week. This book is divided in the following chapters: in chapter \ref{installation} I will provide the basic installation instructions and execution of the Python interpreter. In chapter \ref{basic-datatypes} we will talk about the most basic data types, numbers and strings. In chapter \ref{functions} we will start tinkering with functions, and in chapter \ref{loops} the topic is about "loops". In chapter \ref{dictionaries} we will work with dictionaries and finally, in chapter \ref{classes} we will finish the book with some exercises about classes and object oriented programming. Please note that this book is a work in progress and as such may contain quite a few spelling errors that may be corrected in the future. However it is made available as it is so it can be useful to anyone who wants to use it. I sincerely hope you can get something good through it. -This book is made available in github (check it at \url{https://github.com/joaoventura/full-speed-python}) so I appreciate any pull requests to correct misspellings or to suggest new exercises or clarification of the current content. +This book is made available in github (check it at \url{https://github.com/joaoventura/full-speed-python}) so I welcome any pull requests to correct misspellings, to suggest new exercises or clarification of the current content. -Best wishes, +All the best, João Ventura - Adjunct Professor at the Escola Superior de Tecnologia de Setúbal diff --git a/full-speed-python.tex b/full-speed-python.tex index 8c94697..a6e3dbe 100644 --- a/full-speed-python.tex +++ b/full-speed-python.tex @@ -41,9 +41,9 @@ \begin{document} -\title{At full speed with Python} +\title{Getting up to speed with Python} \author{João Ventura} -\date{v0.1} +\date{v0.2} \maketitle From ac8c77bfa2ee38513ad7294ba9b6adab14d7547e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Tue, 20 Mar 2018 12:20:55 +0000 Subject: [PATCH 03/59] Remove gzip files on clean --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 09e20dd..934f3eb 100644 --- a/Makefile +++ b/Makefile @@ -10,4 +10,4 @@ pdf: clean: rm *.epub *.pdf rm chapters/*.aux - rm *.aux *.log *.out *.toc + rm *.aux *.log *.out *.toc *.gz From 14af71838d96f217ca19faae5642787373044aa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ventura?= Date: Tue, 20 Mar 2018 12:27:48 +0000 Subject: [PATCH 04/59] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 415455e..f1f13ac 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This book aims to teach the basics of the python programming language using a pr These exercises have been used extensively in my web development and distributed computing classes at the Superior School of Technology of Setúbal. With these exercises, most students are up to speed with Python in less than a month. In fact, students of the distributed computing course, taught in the second year of the software engineering degree, become familiar with Python's syntax in two weeks and are able to implement a distributed client-server application with sockets in the third week. -This book is made available in github (https://github.com/joaoventura/full-speed-python) so I appreciate any pull requests to correct misspellings or to suggest new exercises or clarification of the current content. +This book is made available in github (https://github.com/joaoventura/full-speed-python) so I welcome any pull requests to correct misspellings, to suggest new exercises or clarification of the current content. ## Building From 2a0c420e94e3aae14ab32adf73ccf690b145c5de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Zawadzki?= Date: Tue, 20 Mar 2018 13:55:24 +0100 Subject: [PATCH 05/59] Fix the typo --- chapters/classes.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/classes.tex b/chapters/classes.tex index cff7c1f..818569f 100644 --- a/chapters/classes.tex +++ b/chapters/classes.tex @@ -74,7 +74,7 @@ \section{Exercises with inheritance} \item Create a "Square" class as subclass of "Rectangle". -\item Implement the "Square" constructor. The constructor should have only the x1, y1 coordinates and the size of the square. Notice which arguments you'll have to use when you invoce the "Rectangle" constructor when you use "super". +\item Implement the "Square" constructor. The constructor should have only the x1, y1 coordinates and the size of the square. Notice which arguments you'll have to use when you invoke the "Rectangle" constructor when you use "super". \item Instantiate two objects of "Square", invoke the area method and print the objects. Make sure that all calculations are returning correct numbers and that the coordinates of the squares are consistent with the size of the square used as argument. From 27bd51b1f7d5f95a59da811feac51fe801559182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Zawadzki?= Date: Tue, 20 Mar 2018 14:36:14 +0100 Subject: [PATCH 06/59] Keys cannot be any type of objects Official docs says: https://docs.python.org/3/tutorial/datastructures.html#dictionaries ```Unlike sequences, which are indexed by a range of numbers, dictionaries are indexed by keys, which can be any immutable type; strings and numbers can always be keys. ``` As far I understand that this is practical and basic introduction - there should be explained difference between immutable vs mutable types - especially with the dictionary keys case. --- chapters/dictionaries.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/dictionaries.tex b/chapters/dictionaries.tex index b65b74b..67dfc56 100644 --- a/chapters/dictionaries.tex +++ b/chapters/dictionaries.tex @@ -34,7 +34,7 @@ \chapter{Dictionaries}\label{dictionaries} Gabriel 10 \end{lstlisting} -However, keys don't need to be necessarily strings and integers but can be any objects: +However, keys don't need to be necessarily strings and integers but can be any [immutable](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) objects: \begin{lstlisting} d = { From f36baa1b6529ec434d0d2ff28fe4c9e4fda350f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Tue, 20 Mar 2018 17:47:46 +0000 Subject: [PATCH 07/59] Fix url in dictionaries chapter --- chapters/dictionaries.tex | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/chapters/dictionaries.tex b/chapters/dictionaries.tex index 67dfc56..62592e5 100644 --- a/chapters/dictionaries.tex +++ b/chapters/dictionaries.tex @@ -23,7 +23,7 @@ \chapter{Dictionaries}\label{dictionaries} \begin{lstlisting} >>> for name, age in ages.items(): ... print(name, age) -... +... Peter 10 Isabel 11 Anna 9 @@ -34,7 +34,7 @@ \chapter{Dictionaries}\label{dictionaries} Gabriel 10 \end{lstlisting} -However, keys don't need to be necessarily strings and integers but can be any [immutable](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) objects: +However, dictionary keys don't need to be necessarily strings but can be any \href{https://docs.python.org/3/tutorial/datastructures.html#dictionaries}{immutable} object: \begin{lstlisting} d = { @@ -47,7 +47,7 @@ \chapter{Dictionaries}\label{dictionaries} [2, 2, 2] \end{lstlisting} -Even more, you can use other dictionaries as values: +And you can also use other dictionaries as values: \begin{lstlisting} students = { @@ -62,7 +62,7 @@ \chapter{Dictionaries}\label{dictionaries} 'Lisbon' \end{lstlisting} -This is quite useful to structure hierarchical information. +This is quite useful to structure hierarchical information. \section{Exercises with dictionaries} @@ -113,6 +113,6 @@ \section{Exercises with sub-dictionaries} \item Implement a function that receives the students dict and returns the average age. -\item Implement a function that receives the students dict and an address, and returns a list with the name of all students which address matches the address in the argument. For instance, invoking "find\_students(students, 'Lisbon')" should return Peter and Anna. +\item Implement a function that receives the students dict and an address, and returns a list with the name of all students which address matches the address in the argument. For instance, invoking "find\_students(students, 'Lisbon')" should return Peter and Anna. \end{enumerate} From 0a94ac79986b8d3b91f27526b438f975a25454ce Mon Sep 17 00:00:00 2001 From: dunkthelunk Date: Wed, 21 Mar 2018 01:29:31 +0530 Subject: [PATCH 08/59] line.replace('find', 'use') --- chapters/basic-datatypes.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/basic-datatypes.tex b/chapters/basic-datatypes.tex index 5428d73..b189029 100644 --- a/chapters/basic-datatypes.tex +++ b/chapters/basic-datatypes.tex @@ -121,7 +121,7 @@ \section{Exercises with strings} \item Use a function that allows you to replace all occurences of "a" to "X", and then use the same function to change only the first occurence of "a" to "X". \end{enumerate} -\item Starting from the string "aaa bbb ccc", what sequences of operations do you need to arrive at the following strings? You can find the "replace" function. +\item Starting from the string "aaa bbb ccc", what sequences of operations do you need to arrive at the following strings? You can use the "replace" function. \begin{enumerate} \item "AAA BBB CCC" \item "AAA bbb CCC" From 40c758d67746c496b5eded388a4eaab7e44e2e55 Mon Sep 17 00:00:00 2001 From: Filipe Filardi Date: Tue, 20 Mar 2018 21:46:15 -0300 Subject: [PATCH 09/59] Add new instructions for installation on linux - Fix broken url - Change command to check if you already have python to python3 --version --- chapters/installation.tex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/chapters/installation.tex b/chapters/installation.tex index f91aab7..3192523 100644 --- a/chapters/installation.tex +++ b/chapters/installation.tex @@ -54,11 +54,11 @@ \section{Installing on macOS} \section{Installing on Linux} -For Linux, you can download the latest Python 3 binary releases from \url{https://www.python.org/downloads/linux/} or use your package manager to install it. To make sure you have Python 3 installed on your system, run $python3$ in your terminal. +To install python on Linux, you can download the latest Python 3 binary releases from \url{https://www.python.org/downloads/source/} or use your package manager (apt-get, aptitude, synaptic and others) to install it. To make sure you have Python 3 installed on your system, run $python3 --version$ in your terminal. + +Finally, open the terminal, execute $python3$ and you should see the Python REPL as the following image. Press Ctrl+D or write $exit()$ to leave the REPL. \begin{figure}[H] \centering \includegraphics[width=0.62\textwidth]{images/python_linux.png} \end{figure} - -Finally, open the terminal, execute $python3$ and you should see the Python REPL as above. Press Ctrl+D or write $exit()$ to leave the REPL. From be0598a934358da9294e58c78882d238883060c1 Mon Sep 17 00:00:00 2001 From: Filipe Filardi Date: Wed, 21 Mar 2018 07:06:48 -0300 Subject: [PATCH 10/59] update fix --- chapters/installation.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/installation.tex b/chapters/installation.tex index 3192523..ab78f11 100644 --- a/chapters/installation.tex +++ b/chapters/installation.tex @@ -54,7 +54,7 @@ \section{Installing on macOS} \section{Installing on Linux} -To install python on Linux, you can download the latest Python 3 binary releases from \url{https://www.python.org/downloads/source/} or use your package manager (apt-get, aptitude, synaptic and others) to install it. To make sure you have Python 3 installed on your system, run $python3 --version$ in your terminal. +To install Python on Linux, you can download the latest Python 3 source releases from \url{https://www.python.org/downloads/source/} or use your package manager (apt-get, aptitude, synaptic and others) to install it. To make sure you have Python 3 installed on your system, run $python3 --version$ in your terminal. Finally, open the terminal, execute $python3$ and you should see the Python REPL as the following image. Press Ctrl+D or write $exit()$ to leave the REPL. From a6b920873fefc6dc05ccb83e46e524e924592f0f Mon Sep 17 00:00:00 2001 From: Friedrich Politz Date: Wed, 21 Mar 2018 18:32:02 +0100 Subject: [PATCH 11/59] Added better documentation resource The current link does not provide first hand documentation to actually solve the assignments. --- chapters/basic-datatypes.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/basic-datatypes.tex b/chapters/basic-datatypes.tex index b189029..4847088 100644 --- a/chapters/basic-datatypes.tex +++ b/chapters/basic-datatypes.tex @@ -105,7 +105,7 @@ \section{Exercises with numbers} \section{Exercises with strings} -Using the Python documentation on strings (\url{https://docs.python.org/3/library/string.html}), solve the following exercises: +Using the Python documentation on strings (\url{https://docs.python.org/3/library/stdtypes.html?highlight=rfind#text-sequence-type-str}), solve the following exercises: \begin{enumerate} From 9a14d269a6fc9e0875deba06df2ca11ccd8fcb84 Mon Sep 17 00:00:00 2001 From: Friedrich Politz Date: Wed, 21 Mar 2018 18:33:14 +0100 Subject: [PATCH 12/59] Fix --- chapters/basic-datatypes.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/basic-datatypes.tex b/chapters/basic-datatypes.tex index 4847088..02d4b2c 100644 --- a/chapters/basic-datatypes.tex +++ b/chapters/basic-datatypes.tex @@ -105,7 +105,7 @@ \section{Exercises with numbers} \section{Exercises with strings} -Using the Python documentation on strings (\url{https://docs.python.org/3/library/stdtypes.html?highlight=rfind#text-sequence-type-str}), solve the following exercises: +Using the Python documentation on strings (\url{https://docs.python.org/3/library/stdtypes.html?#text-sequence-type-str}), solve the following exercises: \begin{enumerate} From 2a86a826ceaa1102fe4df36176756c6a45d5fc8a Mon Sep 17 00:00:00 2001 From: dunkthelunk Date: Thu, 22 Mar 2018 00:44:13 +0530 Subject: [PATCH 13/59] fix typo --- chapters/functions.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/functions.tex b/chapters/functions.tex index 0d1f9a2..496aa7c 100644 --- a/chapters/functions.tex +++ b/chapters/functions.tex @@ -61,7 +61,7 @@ \section{Exercises with functions} \item Implement a function that returns the greatest of two numbers given as parameters. Use the "if" statement to compare both numbers: \url{https://docs.python.org/3/tutorial/controlflow.html#if-statements}. -\item Implement a function named "is\_divisable" that receives two parameters (named "a" and "b") and returns true if "a" can be divided by "b" or false otherwise. A number is divisable by another when the remainder of the division is zero. Use the modulo operator ("\%"). +\item Implement a function named "is\_divisible" that receives two parameters (named "a" and "b") and returns true if "a" can be divided by "b" or false otherwise. A number is divisible by another when the remainder of the division is zero. Use the modulo operator ("\%"). \item Create a function named "average" that computes the average value of a list passed as parameter to the function. Use the "sum" and "len" functions. From ddfc0c7521c2029774823f2c11b1168283a80ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Thu, 22 Mar 2018 15:45:49 +0000 Subject: [PATCH 14/59] Several fixes and simplification of texts --- chapters/basic-datatypes.tex | 4 ++-- chapters/installation.tex | 4 ++-- chapters/introduction.tex | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/chapters/basic-datatypes.tex b/chapters/basic-datatypes.tex index 02d4b2c..654b7a6 100644 --- a/chapters/basic-datatypes.tex +++ b/chapters/basic-datatypes.tex @@ -44,14 +44,14 @@ \chapter{Basic datatypes}\label{basic-datatypes} TypeError: must be str, not int \end{lstlisting} -However, multiplication seems to work as repetition: +However, multiplication works as repetition: \begin{lstlisting} >>> "Hello" * 3 'HelloHelloHello' \end{lstlisting} -Finally, Python also supports the list datatype. Lists are data structures that allows us to group some values. Lists can have values of several types and you can also mix different types within the same list although usually all values are usually of the same datatype. +Finally, Python also supports the list datatype. Lists are data structures that allows us to group some values. Lists can have values of several types and you can also mix different types within the same list although all values are usually of the same datatype. Lists are created by starting and ending with square brackets and separated by commas. The values in a list can be accessed by its position where 0 is the index of the first value: diff --git a/chapters/installation.tex b/chapters/installation.tex index ab78f11..38ea5ea 100644 --- a/chapters/installation.tex +++ b/chapters/installation.tex @@ -42,7 +42,7 @@ \section{Installing on Windows} \section{Installing on macOS} -You can download the latest macOS binary releases from \url{https://www.python.org/downloads/mac-osx/}. Make sure you download the latest Python 3 release (3.6.4 at the time of writing). You can also use Homebrew, a package manager for macOS (\url{https://brew.sh/}). To install the latest Python 3 release with Homebrew, just do "\texttt{brew install python3}" on your terminal. Another option is to use MacPorts package manager (\url{https://www.macports.org/}) and command "\texttt{port install python36}". +You can download the latest macOS binary releases from \url{https://www.python.org/downloads/mac-osx/}. Make sure you download the latest Python 3 release (3.6.4 at the time of writing). You can also use Homebrew, a package manager for macOS (\url{https://brew.sh/}). To install the latest Python 3 release with Homebrew, just do "\texttt{brew install python3}" on your terminal. Another option is to use the MacPorts package manager (\url{https://www.macports.org/}) and command "\texttt{port install python36}". \begin{figure}[H] @@ -56,7 +56,7 @@ \section{Installing on Linux} To install Python on Linux, you can download the latest Python 3 source releases from \url{https://www.python.org/downloads/source/} or use your package manager (apt-get, aptitude, synaptic and others) to install it. To make sure you have Python 3 installed on your system, run $python3 --version$ in your terminal. -Finally, open the terminal, execute $python3$ and you should see the Python REPL as the following image. Press Ctrl+D or write $exit()$ to leave the REPL. +Finally, open the terminal, execute $python3$ and you should see the Python REPL as in the following image. Press Ctrl+D or write $exit()$ to leave the REPL. \begin{figure}[H] \centering diff --git a/chapters/introduction.tex b/chapters/introduction.tex index ce1a4c7..626937f 100644 --- a/chapters/introduction.tex +++ b/chapters/introduction.tex @@ -1,15 +1,15 @@ \chapter{Introduction}\label{introduction} -This book aims to teach the basics of the Python programming language using a practical approach. Its method is quite basic though: after a very simple introduction to each topic, the reader is invited to learn by solving the proposed exercises. +This book aims to teach the basics of the Python programming language using a practical approach. Its method is quite basic though: after a simple introduction to each topic, the reader is invited to learn by solving the proposed exercises. These exercises have been used extensively in my web development and distributed computing classes at the Superior School of Technology of Setúbal. With these exercises, most students are up to speed with Python in less than a month. In fact, students of the distributed computing course, taught in the second year of the software engineering degree, become familiar with Python's syntax in two weeks and are able to implement a distributed client-server application with sockets in the third week. This book is divided in the following chapters: in chapter \ref{installation} I will provide the basic installation instructions and execution of the Python interpreter. In chapter \ref{basic-datatypes} we will talk about the most basic data types, numbers and strings. In chapter \ref{functions} we will start tinkering with functions, and in chapter \ref{loops} the topic is about "loops". In chapter \ref{dictionaries} we will work with dictionaries and finally, in chapter \ref{classes} we will finish the book with some exercises about classes and object oriented programming. -Please note that this book is a work in progress and as such may contain quite a few spelling errors that may be corrected in the future. However it is made available as it is so it can be useful to anyone who wants to use it. I sincerely hope you can get something good through it. +Please note that this book is a work in progress and, as such, may contain quite a few spelling errors that may be corrected in the future. However it is made available as it is so it can be useful to anyone who wants to use it. I sincerely hope you can get something good through it. -This book is made available in github (check it at \url{https://github.com/joaoventura/full-speed-python}) so I welcome any pull requests to correct misspellings, to suggest new exercises or clarification of the current content. +The source of this book is made available in github (check it at \url{https://github.com/joaoventura/full-speed-python}) so I welcome any pull requests to correct misspellings, suggest new exercises or to provide clarification of the current content. All the best, -João Ventura - Adjunct Professor at the Escola Superior de Tecnologia de Setúbal +João Ventura - Adjunct Professor at the Escola Superior de Tecnologia de Setúbal. From 126414cea2fc068a377fb5161d87ec58f988bde3 Mon Sep 17 00:00:00 2001 From: dunkthelunk Date: Sun, 25 Mar 2018 00:28:38 +0530 Subject: [PATCH 15/59] fix typos and grammar --- chapters/dictionaries.tex | 6 +++--- chapters/loops.tex | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/chapters/dictionaries.tex b/chapters/dictionaries.tex index 62592e5..2ab2efd 100644 --- a/chapters/dictionaries.tex +++ b/chapters/dictionaries.tex @@ -34,7 +34,7 @@ \chapter{Dictionaries}\label{dictionaries} Gabriel 10 \end{lstlisting} -However, dictionary keys don't need to be necessarily strings but can be any \href{https://docs.python.org/3/tutorial/datastructures.html#dictionaries}{immutable} object: +However, dictionary keys don't necessarily need to be strings but can be any \href{https://docs.python.org/3/tutorial/datastructures.html#dictionaries}{immutable} object: \begin{lstlisting} d = { @@ -87,7 +87,7 @@ \section{Exercises with dictionaries} \item How many students are in the dictionary? Search for the "len" function. -\item Implement a function that receives the "ages" dictionary as parameter and return the average age of the students. Traverse all items on the dictionary using the "items" method as above. +\item Implement a function that receives the "ages" dictionary as parameter and returns the average age of the students. Traverse all items on the dictionary using the "items" method as above. \item Implement a function that receives the "ages" dictionary as parameter and returns the name of the oldest student. @@ -113,6 +113,6 @@ \section{Exercises with sub-dictionaries} \item Implement a function that receives the students dict and returns the average age. -\item Implement a function that receives the students dict and an address, and returns a list with the name of all students which address matches the address in the argument. For instance, invoking "find\_students(students, 'Lisbon')" should return Peter and Anna. +\item Implement a function that receives the students dict and an address, and returns a list with names of all students whose address matches the address in the argument. For instance, invoking "find\_students(students, 'Lisbon')" should return Peter and Anna. \end{enumerate} diff --git a/chapters/loops.tex b/chapters/loops.tex index 099bda2..f76678b 100644 --- a/chapters/loops.tex +++ b/chapters/loops.tex @@ -97,11 +97,11 @@ \section{Exercises with the for loop} \item Create a function that receives a list as parameter and returns the maximum value in the list. As you iterate over the list you may want to keep the maximum value found so far in order to keep comparing it with the next elements of the list. -\item Modify the previous function such that it returns a list with the first element being the maximum value and the second being the index of the maximum value in the list. Besides keep the last maximum value found so far, you need to keep also the position where it occured. +\item Modify the previous function such that it returns a list with the first element being the maximum value and the second being the index of the maximum value in the list. Besides keeping the maximum value found so far, you also need to keep the position where it occurred. \item Implement a function that returns the reverse of a list received as parameter. You may create an empty list and keep adding the values in reversed order as they come from the original list. Check what you can do with lists at \url{https://docs.python.org/3/tutorial/datastructures.html#more-on-lists}. -\item Make the function "is\_sorted" that receives a list as parameter and returns True if the list is sorted by increasing order. For instance [1, 2, 2, 3] is ordered while [1, 2, 3, 2] is not. Suggestion: you have to compare a number in the list with the next one, so you can use indexes or you need to keep the previous number in a variable as you iterate over the list. +\item Make the function "is\_sorted" that receives a list as parameter and returns True if the list is sorted in ascending order. For instance [1, 2, 2, 3] is ordered while [1, 2, 3, 2] is not. Suggestion: you have to compare a number in the list with the next one, so you can use indexes or you need to keep the previous number in a variable as you iterate over the list. \item Implement the function "is\_sorted\_dec" which is similar to the previous one but all items must be sorted by decreasing order. From 34a048072794e19685f7fd87679cdeaf46be6c75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Tue, 27 Mar 2018 15:17:15 +0100 Subject: [PATCH 16/59] Change book title --- README.md | 6 +++--- chapters/introduction.tex | 6 +++--- full-speed-python.tex | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f1f13ac..4a14ab4 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# Getting up to speed with Python +# Full Speed Python Pdf and epub files can be downloaded from: https://github.com/joaoventura/full-speed-python/releases/ -This book aims to teach the basics of the python programming language using a practical approach. Its method is quite basic though: after a very simple introduction to each topic, the reader is invited to learn by solving the proposed exercises. +This book aims to teach the Python programming language using a practical approach. Its method is quite simple: after a short introduction to each topic, the reader is invited to learn more by solving the proposed exercises. These exercises have been used extensively in my web development and distributed computing classes at the Superior School of Technology of Setúbal. With these exercises, most students are up to speed with Python in less than a month. In fact, students of the distributed computing course, taught in the second year of the software engineering degree, become familiar with Python's syntax in two weeks and are able to implement a distributed client-server application with sockets in the third week. -This book is made available in github (https://github.com/joaoventura/full-speed-python) so I welcome any pull requests to correct misspellings, to suggest new exercises or clarification of the current content. +The source of this book is available on github (https://github.com/joaoventura/full-speed-python). I welcome any pull requests to correct misspellings, suggest new exercises or to provide clarification of the current content. ## Building diff --git a/chapters/introduction.tex b/chapters/introduction.tex index 626937f..b06051f 100644 --- a/chapters/introduction.tex +++ b/chapters/introduction.tex @@ -1,14 +1,14 @@ \chapter{Introduction}\label{introduction} -This book aims to teach the basics of the Python programming language using a practical approach. Its method is quite basic though: after a simple introduction to each topic, the reader is invited to learn by solving the proposed exercises. +This book aims to teach the Python programming language using a practical approach. Its method is quite simple: after a short introduction to each topic, the reader is invited to learn more by solving the proposed exercises. These exercises have been used extensively in my web development and distributed computing classes at the Superior School of Technology of Setúbal. With these exercises, most students are up to speed with Python in less than a month. In fact, students of the distributed computing course, taught in the second year of the software engineering degree, become familiar with Python's syntax in two weeks and are able to implement a distributed client-server application with sockets in the third week. This book is divided in the following chapters: in chapter \ref{installation} I will provide the basic installation instructions and execution of the Python interpreter. In chapter \ref{basic-datatypes} we will talk about the most basic data types, numbers and strings. In chapter \ref{functions} we will start tinkering with functions, and in chapter \ref{loops} the topic is about "loops". In chapter \ref{dictionaries} we will work with dictionaries and finally, in chapter \ref{classes} we will finish the book with some exercises about classes and object oriented programming. -Please note that this book is a work in progress and, as such, may contain quite a few spelling errors that may be corrected in the future. However it is made available as it is so it can be useful to anyone who wants to use it. I sincerely hope you can get something good through it. +Please note that this book is a work in progress and, as such, may contain a few spelling errors that may be corrected in the future. However it is made available now as it is so it can be useful to anyone who wants to use it. I sincerely hope you can get something good through it. -The source of this book is made available in github (check it at \url{https://github.com/joaoventura/full-speed-python}) so I welcome any pull requests to correct misspellings, suggest new exercises or to provide clarification of the current content. +The source of this book is available on github (\url{https://github.com/joaoventura/full-speed-python}). I welcome any pull requests to correct misspellings, suggest new exercises or to provide clarification of the current content. All the best, diff --git a/full-speed-python.tex b/full-speed-python.tex index a6e3dbe..9cfbf9b 100644 --- a/full-speed-python.tex +++ b/full-speed-python.tex @@ -41,9 +41,9 @@ \begin{document} -\title{Getting up to speed with Python} +\title{Full Speed Python} \author{João Ventura} -\date{v0.2} +\date{v0.3} \maketitle From 1c78dff2f48493b570402bd93fecdf7eee1afd89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Tue, 27 Mar 2018 16:01:41 +0100 Subject: [PATCH 17/59] New chapter iterators --- chapters/introduction.tex | 2 +- chapters/iterators.tex | 106 ++++++++++++++++++++++++++++++++++++++ full-speed-python.tex | 1 + 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 chapters/iterators.tex diff --git a/chapters/introduction.tex b/chapters/introduction.tex index b06051f..192db2d 100644 --- a/chapters/introduction.tex +++ b/chapters/introduction.tex @@ -4,7 +4,7 @@ \chapter{Introduction}\label{introduction} These exercises have been used extensively in my web development and distributed computing classes at the Superior School of Technology of Setúbal. With these exercises, most students are up to speed with Python in less than a month. In fact, students of the distributed computing course, taught in the second year of the software engineering degree, become familiar with Python's syntax in two weeks and are able to implement a distributed client-server application with sockets in the third week. -This book is divided in the following chapters: in chapter \ref{installation} I will provide the basic installation instructions and execution of the Python interpreter. In chapter \ref{basic-datatypes} we will talk about the most basic data types, numbers and strings. In chapter \ref{functions} we will start tinkering with functions, and in chapter \ref{loops} the topic is about "loops". In chapter \ref{dictionaries} we will work with dictionaries and finally, in chapter \ref{classes} we will finish the book with some exercises about classes and object oriented programming. +This book is divided in the following chapters: in chapter \ref{installation} I will provide the basic installation instructions and execution of the Python interpreter. In chapter \ref{basic-datatypes} we will talk about the most basic data types, namely numbers and strings. In chapter \ref{functions} we will start tinkering with functions, and in chapter \ref{loops} the topic is about the for and the while "loops". In chapter \ref{dictionaries} we will work with dictionaries and in chapter \ref{classes} we will work with some exercises about classes and object oriented programming. In chapter \ref{iterators}, we will explore the topic of Python iterators. Please note that this book is a work in progress and, as such, may contain a few spelling errors that may be corrected in the future. However it is made available now as it is so it can be useful to anyone who wants to use it. I sincerely hope you can get something good through it. diff --git a/chapters/iterators.tex b/chapters/iterators.tex new file mode 100644 index 0000000..467c18d --- /dev/null +++ b/chapters/iterators.tex @@ -0,0 +1,106 @@ +\chapter{Iterators}\label{iterators} + +As we saw previously, in Python we use the "for" loop to iterate over the contents of objects: + +\begin{lstlisting} +>>> for value in [0, 1, 2, 3, 4, 5]: +... print(value) +... +0 +1 +4 +9 +16 +25 +\end{lstlisting} + +Objects that can be used with a "for" loop are called iterators. An iterator is, therefore, an object that follows the iteration protocol. + +The built-in function "iter" can be used to build iterator objects, while the "next" function can be used to gradually iterate over their content: + +\begin{lstlisting} +>>> my_iter = iter([1, 2, 3]) +>>> my_iter + +>>> next(my_iter) +1 +>>> next(my_iter) +2 +>>> next(my_iter) +3 +>>> next(my_iter) +Traceback (most recent call last): + File "", line 1, in +StopIteration +\end{lstlisting} + +If there are no more elements, the iterator raises a "StopIteration" exception. + +\section{Iterator classes} + +Iterators can be implemented as classes. You just need to implement the "\_\_next\_\_" and "\_\_iter\_\_" methods. Here's an example of a class that mimics the "range" function, returning all values from "a" to "b": + +\begin{lstlisting} +class MyRange: + + def __init__(self, a, b): + self.a = a + self.b = b + + def __iter__(self): + return self + + def __next__(self): + if self.a < self.b: + value = self.a + self.a += 1 + return value + else: + raise StopIteration +\end{lstlisting} + +Basically, on every call to "next" it moves forward the internal variable "a" and returns its value. When it reaches "b", it raises the StopIteration exception. + +\begin{lstlisting} +>>> myrange = MyRange(1, 4) +>>> next(myrange) +1 +>>> next(myrange) +2 +>>> next(myrange) +3 +>>> next(myrange) +Traceback (most recent call last): + File "", line 1, in +StopIteration +\end{lstlisting} + +But most important, you can use the iterator class in a "for" loop: + +\begin{lstlisting} +>>> for value in MyRange(1, 4): +... print(value) +... +1 +2 +3 +\end{lstlisting} + + +\section{Exercises with iterators} + +\begin{enumerate} + +\item Implement an iterator class to return the square of all numbers from "a" to "b". + +\item Implement an iterator class to return all the even numbers from 1 to $n$. + +\item Implement an iterator class to return all the odd numbers from 1 to $n$. + +\item Implement an iterator class to return all numbers from $n$ down to 0. + +\item Implement an iterator class to return the fibonnaci sequence from the first element up to $n$. You can check the definition of the fibonnaci sequence in the function's chapter. These are the first numbers of the sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... + +\item Implement an iterator class to return all consecutive pairs of numbers from 0 until $n$, such as (0, 1), (1, 2), (2, 3)... + +\end{enumerate} \ No newline at end of file diff --git a/full-speed-python.tex b/full-speed-python.tex index 9cfbf9b..c2cd555 100644 --- a/full-speed-python.tex +++ b/full-speed-python.tex @@ -59,5 +59,6 @@ \include{chapters/loops} \include{chapters/dictionaries} \include{chapters/classes} +\include{chapters/iterators} \end{document} From 335f921b54cf14f7c50d0df544406b6302ac2f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 00:13:34 +0100 Subject: [PATCH 18/59] New chapter about generators --- chapters/generators.tex | 66 +++++++++++++++++++++++++++++++++++++++ chapters/introduction.tex | 2 +- full-speed-python.tex | 1 + 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 chapters/generators.tex diff --git a/chapters/generators.tex b/chapters/generators.tex new file mode 100644 index 0000000..ec7d493 --- /dev/null +++ b/chapters/generators.tex @@ -0,0 +1,66 @@ +\chapter{Generators}\label{generators} + +If you read the previous chapter, you know that iterators are objects that are regularly used with "for" loops. In other others, iterators are objects that implement the iteration protocol. A Python generator is a convenient way to implement an iterator. Instead of a class, a generator is a function which returns a value each time the "yield" keyword is used. Here's an example of a generator to count the values between two numbers: + +\begin{lstlisting} +def myrange(a, b): + while a < b: + yield a + a += 1 +\end{lstlisting} + +Like iterators, generators can be used with the "for" loop: + +\begin{lstlisting} +>>> for value in myrange(1, 4): +... print(value) +... +1 +2 +3 +\end{lstlisting} + +Under the hood, generators behave similarly to iterators: + +\begin{lstlisting} +>>> seq = myrange(1,3) +>>> next(seq) +1 +>>> next(seq) +2 +>>> next(seq) +Traceback (most recent call last): + File "", line 1, in +StopIteration +\end{lstlisting} + +The interesting thing about generators is the "yield" keyword. The "yield" keyword works much like the "return" keyword, but unlike "return", it allows the function to eventually resume its execution. In other words, each time the next value of a generator is needed, Python wakes up the function and resumes its execution from the "yield" line as if the function had never exited. + +Generator functions can use other functions inside. For instance, it is very common to use the "range" function to iterate over a sequence of numbers: + +\begin{lstlisting} +def squares(n): + for value in range(n): + yield value * value +\end{lstlisting} + +\section{Exercises with generators} + +\begin{enumerate} + +\item Implement a generator called "squares" to yield the square of all numbers from $a$ to $b$. Test it with a "for" loop and print each of the yielded values. + +\item Create a generator to yield all the even numbers from 1 to $n$. + +\item Create another generator to yield all the odd numbers from 1 to $n$. + +\item Implement a generator that returns all numbers from $n$ down to 0. + +\item Create a generator to return the fibonnaci sequence starting from the first element up to $n$. The first numbers of the sequence are: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... + +\item Implement a generator that returns all consecutive pairs of numbers from 0 to $n$, such as (0, 1), (1, 2), (2, 3)... + +\end{enumerate} + + + diff --git a/chapters/introduction.tex b/chapters/introduction.tex index 192db2d..9349c23 100644 --- a/chapters/introduction.tex +++ b/chapters/introduction.tex @@ -4,7 +4,7 @@ \chapter{Introduction}\label{introduction} These exercises have been used extensively in my web development and distributed computing classes at the Superior School of Technology of Setúbal. With these exercises, most students are up to speed with Python in less than a month. In fact, students of the distributed computing course, taught in the second year of the software engineering degree, become familiar with Python's syntax in two weeks and are able to implement a distributed client-server application with sockets in the third week. -This book is divided in the following chapters: in chapter \ref{installation} I will provide the basic installation instructions and execution of the Python interpreter. In chapter \ref{basic-datatypes} we will talk about the most basic data types, namely numbers and strings. In chapter \ref{functions} we will start tinkering with functions, and in chapter \ref{loops} the topic is about the for and the while "loops". In chapter \ref{dictionaries} we will work with dictionaries and in chapter \ref{classes} we will work with some exercises about classes and object oriented programming. In chapter \ref{iterators}, we will explore the topic of Python iterators. +This book is divided in the following chapters: in chapter \ref{installation} I will provide the basic installation instructions and execution of the Python interpreter. In chapter \ref{basic-datatypes} we will talk about the most basic data types, namely numbers and strings. In chapter \ref{functions} we will start tinkering with functions, and in chapter \ref{loops} the topic is about the for and the while "loops". In chapter \ref{dictionaries} we will work with dictionaries and in chapter \ref{classes} we will work with some exercises about classes and object oriented programming. In chapter \ref{iterators}, we will explore the topic of Python iterators and in chapter \ref{generators} we will talk about Python generators. Please note that this book is a work in progress and, as such, may contain a few spelling errors that may be corrected in the future. However it is made available now as it is so it can be useful to anyone who wants to use it. I sincerely hope you can get something good through it. diff --git a/full-speed-python.tex b/full-speed-python.tex index c2cd555..c2f0afd 100644 --- a/full-speed-python.tex +++ b/full-speed-python.tex @@ -60,5 +60,6 @@ \include{chapters/dictionaries} \include{chapters/classes} \include{chapters/iterators} +\include{chapters/generators} \end{document} From b136c74358d7c495b7977dde5c3a89524bcb4348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 09:14:03 +0100 Subject: [PATCH 19/59] Remove chapter contents from introduction --- chapters/introduction.tex | 2 -- 1 file changed, 2 deletions(-) diff --git a/chapters/introduction.tex b/chapters/introduction.tex index 9349c23..a84043b 100644 --- a/chapters/introduction.tex +++ b/chapters/introduction.tex @@ -4,8 +4,6 @@ \chapter{Introduction}\label{introduction} These exercises have been used extensively in my web development and distributed computing classes at the Superior School of Technology of Setúbal. With these exercises, most students are up to speed with Python in less than a month. In fact, students of the distributed computing course, taught in the second year of the software engineering degree, become familiar with Python's syntax in two weeks and are able to implement a distributed client-server application with sockets in the third week. -This book is divided in the following chapters: in chapter \ref{installation} I will provide the basic installation instructions and execution of the Python interpreter. In chapter \ref{basic-datatypes} we will talk about the most basic data types, namely numbers and strings. In chapter \ref{functions} we will start tinkering with functions, and in chapter \ref{loops} the topic is about the for and the while "loops". In chapter \ref{dictionaries} we will work with dictionaries and in chapter \ref{classes} we will work with some exercises about classes and object oriented programming. In chapter \ref{iterators}, we will explore the topic of Python iterators and in chapter \ref{generators} we will talk about Python generators. - Please note that this book is a work in progress and, as such, may contain a few spelling errors that may be corrected in the future. However it is made available now as it is so it can be useful to anyone who wants to use it. I sincerely hope you can get something good through it. The source of this book is available on github (\url{https://github.com/joaoventura/full-speed-python}). I welcome any pull requests to correct misspellings, suggest new exercises or to provide clarification of the current content. From 2f4b37839a088047741004e2d81017f17a10a7f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 09:14:28 +0100 Subject: [PATCH 20/59] Split lists into new chapter --- chapters/basic-datatypes.tex | 49 +----------------------------------- chapters/lists.tex | 49 ++++++++++++++++++++++++++++++++++++ full-speed-python.tex | 1 + 3 files changed, 51 insertions(+), 48 deletions(-) create mode 100644 chapters/lists.tex diff --git a/chapters/basic-datatypes.tex b/chapters/basic-datatypes.tex index 654b7a6..8013bae 100644 --- a/chapters/basic-datatypes.tex +++ b/chapters/basic-datatypes.tex @@ -1,6 +1,6 @@ \chapter{Basic datatypes}\label{basic-datatypes} -In this chapter we will work with the most basic datatypes, numbers, strings and lists. Start your Python REPL and write the following on it: +In this chapter we will work with the most basic datatypes, numbers and strings. Start your Python REPL and write the following: \begin{lstlisting} >>> a = 2 @@ -51,37 +51,6 @@ \chapter{Basic datatypes}\label{basic-datatypes} 'HelloHelloHello' \end{lstlisting} -Finally, Python also supports the list datatype. Lists are data structures that allows us to group some values. Lists can have values of several types and you can also mix different types within the same list although all values are usually of the same datatype. - -Lists are created by starting and ending with square brackets and separated by commas. The values in a list can be accessed by its position where 0 is the index of the first value: - -\begin{lstlisting} ->>> l = [1, 2, 3, 4, 5] ->>> l[0] -1 ->>> l[1] -2 -\end{lstlisting} - -Can you access the number 4 in the previous list? - -Sometimes you want just a small portion of a list, a sublist. Sublists can be retrieved using a technique called \textit{slicing}, which consists on using the start and end indexes on the sublist: - -\begin{lstlisting} ->>> l = ['a', 'b', 'c', 'd', 'e'] ->>> l[1:3] -['b', 'c'] -\end{lstlisting} - -Finally, there's also some arithmetic that you can do on lists, like adding two lists together or repeating the contents of a list. - -\begin{lstlisting} ->>> [1,2] + [3,4] -[1, 2, 3, 4] ->>> [1,2] * 2 -[1, 2, 1, 2] -\end{lstlisting} - \section{Exercises with numbers} @@ -128,19 +97,3 @@ \section{Exercises with strings} \end{enumerate} \end{enumerate} - -\section{Exercises with lists} - -Create a list named "l" with the following values ([1, 4, 9, 10, 23]). Using the Python documentation about lists (\url{https://docs.python.org/3.5/tutorial/introduction.html#lists}) solve the following exercises: - -\begin{enumerate} - -\item Using list slicing get the sublists [4, 9] and [10, 23]. - -\item Append the value 90 to the end of the list "l". Check the difference between list concatenation and the "append" method. - -\item Calculate the average value of all values on the list. You can use the "sum" and "len" functions. - -\item Remove the sublist [4, 9]. - -\end{enumerate} diff --git a/chapters/lists.tex b/chapters/lists.tex new file mode 100644 index 0000000..a43052a --- /dev/null +++ b/chapters/lists.tex @@ -0,0 +1,49 @@ +\chapter{Lists}\label{lists} + +Python lists are data structures that group sequences of elements. Lists can have elements of several types and you can also mix different types within the same list although all elements are usually of the same datatype. + +Lists are created using square brackets and the elements separated by commas. The elements in a list can be accessed by their positions where 0 is the index of the first element: + +\begin{lstlisting} +>>> l = [1, 2, 3, 4, 5] +>>> l[0] +1 +>>> l[1] +2 +\end{lstlisting} + +Can you access the number 4 in the previous list? + +Sometimes you want just a small portion of a list, a sublist. Sublists can be retrieved using a technique called \textit{slicing}, which consists on defining the start and end indexes: + +\begin{lstlisting} +>>> l = ['a', 'b', 'c', 'd', 'e'] +>>> l[1:3] +['b', 'c'] +\end{lstlisting} + +Finally, arithmetic with lists is also possible, like adding two lists together or repeating the contents of a list. + +\begin{lstlisting} +>>> [1,2] + [3,4] +[1, 2, 3, 4] +>>> [1,2] * 2 +[1, 2, 1, 2] +\end{lstlisting} + + +\section{Exercises with lists} + +Create a list named "l" with the following values ([1, 4, 9, 10, 23]). Using the Python documentation about lists (\url{https://docs.python.org/3.5/tutorial/introduction.html#lists}) solve the following exercises: + +\begin{enumerate} + +\item Using list slicing get the sublists [4, 9] and [10, 23]. + +\item Append the value 90 to the end of the list "l". Check the difference between list concatenation and the "append" method. + +\item Calculate the average value of all values on the list. You can use the "sum" and "len" functions. + +\item Remove the sublist [4, 9]. + +\end{enumerate} diff --git a/full-speed-python.tex b/full-speed-python.tex index c2f0afd..7923f7d 100644 --- a/full-speed-python.tex +++ b/full-speed-python.tex @@ -55,6 +55,7 @@ \include{chapters/introduction} \include{chapters/installation} \include{chapters/basic-datatypes} +\include{chapters/lists} \include{chapters/functions} \include{chapters/loops} \include{chapters/dictionaries} From 23d0c4e943576e3f09cf1a302910e4467f315d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 09:47:06 +0100 Subject: [PATCH 21/59] Change basic datatypes chapter name --- chapters/basic-datatypes.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/basic-datatypes.tex b/chapters/basic-datatypes.tex index 8013bae..7982817 100644 --- a/chapters/basic-datatypes.tex +++ b/chapters/basic-datatypes.tex @@ -1,4 +1,4 @@ -\chapter{Basic datatypes}\label{basic-datatypes} +\chapter{Numbers and strings}\label{basic-datatypes} In this chapter we will work with the most basic datatypes, numbers and strings. Start your Python REPL and write the following: From b50845dae92d2b6c865a788e3c72fffd23b4cde7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 09:49:01 +0100 Subject: [PATCH 22/59] Add list comprehensions --- chapters/lists.tex | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/chapters/lists.tex b/chapters/lists.tex index a43052a..3e4f189 100644 --- a/chapters/lists.tex +++ b/chapters/lists.tex @@ -47,3 +47,45 @@ \section{Exercises with lists} \item Remove the sublist [4, 9]. \end{enumerate} + + +\section{List comprehensions} + +List comprehensions are a concise way to create lists. It consists of square brackets containing an expression followed by the "for" keyword. The result will be a list whose results match the expression. Here's how to create a list with the squared numbers of another list. + +\begin{lstlisting} +>>> [x*x for x in [0, 1, 2, 3]] +[0, 1, 4, 9] +\end{lstlisting} + +Given its flexibility, list comprehensions generally make use of the "range" function which returns a range of numbers: + +\begin{lstlisting} +>>> [x*x for x in range(4)] +[0, 1, 4, 9] +\end{lstlisting} + +Sometimes you may want to filter the elements by a given condition. The "if" keyword can be used in those cases: + +\begin{lstlisting} +>>> [x for x in range(10) if x % 2 == 0] +[0, 2, 4, 6, 8] +\end{lstlisting} + +The exemple above returns all even values in range 0..10. More about list comprehensions can be found at \url{https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions}. + +\section{Exercises with list comprehensions} + +\begin{enumerate} + +\item Using list comprehensions, create a list with the squares of the first 10 numbers. + +\item Using list comprehensions, create a list with the cubes of the first 20 numbers. + +\item Create a list comprehension with all the even numbers from 0 to 20, and another one with all the odd numbers. + +\item Create a list with the squares of the even numbers from 0 to 20, and sum the list using the "sum" function. The result should be 1140. First create the list using list comprehensions, check the result, then apply the sum to the list comprehension. + +\item Make a list comprehension that returns a list with the squares of all even numbers from 0 to 20, but ignore those numbers that are divisible by 3. In other words, each number should be divisible by 2 and not divisible by 3. Search for the "and" keyword in the Python documentation. The resulting list is [4, 16, 64, 100, 196, 256]. + +\end{enumerate} From e2ae1dcf426c457a7976bf2121ecf75ad1384ea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 10:08:17 +0100 Subject: [PATCH 23/59] Update makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 934f3eb..09e20dd 100644 --- a/Makefile +++ b/Makefile @@ -10,4 +10,4 @@ pdf: clean: rm *.epub *.pdf rm chapters/*.aux - rm *.aux *.log *.out *.toc *.gz + rm *.aux *.log *.out *.toc From 2602561e72a622ed06e60deae32186411ea257e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 17:07:40 +0100 Subject: [PATCH 24/59] Define latex preamble and metadata --- Makefile | 10 +++++----- metadata.yaml | 12 ++++++++++++ preamble.tex | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 metadata.yaml create mode 100644 preamble.tex diff --git a/Makefile b/Makefile index 09e20dd..1919427 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,13 @@ all: epub pdf epub: - pandoc -o full-speed-python.epub full-speed-python.tex + pandoc -o full-speed-python.epub \ + metadata.yaml \ pdf: - pdflatex full-speed-python.tex - pdflatex full-speed-python.tex + pandoc -o full-speed-python.pdf \ + -H preamble.tex \ + metadata.yaml \ clean: rm *.epub *.pdf - rm chapters/*.aux - rm *.aux *.log *.out *.toc diff --git a/metadata.yaml b/metadata.yaml new file mode 100644 index 0000000..fb28b8d --- /dev/null +++ b/metadata.yaml @@ -0,0 +1,12 @@ +--- +title: Full Speed Python +subtitle: v0.4 +author: João Ventura +language: en-US + +# Variables for Latex +documentclass: book +classoption: oneside +fontsize: 12pt +toc: true +--- diff --git a/preamble.tex b/preamble.tex new file mode 100644 index 0000000..73c68e3 --- /dev/null +++ b/preamble.tex @@ -0,0 +1,42 @@ +% Paper and margins +\usepackage[a4paper, margin=1in]{geometry} + +% Fonts +\usepackage[]{opensans} +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} + +% Paragraphs +\setlength{\parindent}{0pt} +\setlength{\parskip}{6pt plus 2pt minus 1pt} + +% Images +\usepackage{graphicx} +\usepackage{float} + +% All images should be where they are defined +\makeatletter +\def\fps@figure{H} +\makeatother + +% Source code +\usepackage{listings} +\usepackage{xcolor} + +% Source code formatting +\lstset{ + backgroundcolor=\color[rgb]{0.95,0.95,0.95}, + basicstyle=\footnotesize, + language=Python, + aboveskip=1em, + belowskip=1em, +} + +% Headers and footers +\pagestyle{plain} + +% Urls +\usepackage{hyperref} + +% Equations +\usepackage{amsmath} From bfe02d3ee9bf21a0038ba0679fb4bc5df873a14e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 17:33:35 +0100 Subject: [PATCH 25/59] Add introduction --- Makefile | 2 ++ chapters/introduction.md | 13 +++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 chapters/introduction.md diff --git a/Makefile b/Makefile index 1919427..8bc22dc 100644 --- a/Makefile +++ b/Makefile @@ -3,11 +3,13 @@ all: epub pdf epub: pandoc -o full-speed-python.epub \ metadata.yaml \ + chapters/introduction.md \ pdf: pandoc -o full-speed-python.pdf \ -H preamble.tex \ metadata.yaml \ + chapters/introduction.md \ clean: rm *.epub *.pdf diff --git a/chapters/introduction.md b/chapters/introduction.md new file mode 100644 index 0000000..40c507b --- /dev/null +++ b/chapters/introduction.md @@ -0,0 +1,13 @@ +# Introduction + +This book aims to teach the Python programming language using a practical approach. Its method is quite simple: after a short introduction to each topic, the reader is invited to learn more by solving the proposed exercises. + +These exercises have been used extensively in my web development and distributed computing classes at the Superior School of Technology of Setúbal. With these exercises, most students are up to speed with Python in less than a month. In fact, students of the distributed computing course, taught in the second year of the software engineering degree, become familiar with Python’s syntax in two weeks and are able to implement a distributed client-server application with sockets in the third week. + +Please note that this book is a work in progress and, as such, may contain a few spelling errors that may be corrected in the future. However it is made available now as it is so it can be useful to anyone who wants to use it. I sincerely hope you can get something good through it. + +The source of this book is available on github (). I welcome any pull requests to correct misspellings, suggest new exercises or to provide clarification of the current content. + +All the best, + +João Ventura - Adjunct Professor at the Escola Superior de Tecnologia de Setúbal. From 9b9d4c2eb677fe904045dad04cda97b51e1e23ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 17:48:35 +0100 Subject: [PATCH 26/59] Installation chapter --- Makefile | 4 +++- chapters/installation.md | 41 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 chapters/installation.md diff --git a/Makefile b/Makefile index 8bc22dc..e27dddf 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,14 @@ epub: pandoc -o full-speed-python.epub \ metadata.yaml \ chapters/introduction.md \ + chapters/installation.md \ pdf: pandoc -o full-speed-python.pdf \ - -H preamble.tex \ metadata.yaml \ + -H preamble.tex \ chapters/introduction.md \ + chapters/installation.md \ clean: rm *.epub *.pdf diff --git a/chapters/installation.md b/chapters/installation.md new file mode 100644 index 0000000..0dbdcf3 --- /dev/null +++ b/chapters/installation.md @@ -0,0 +1,41 @@ +# Installation + +In this chapter we will install and run the Python interpreter in your local computer. + +## Installing on Windows + +1. Download the latest Python 3 release for Windows on and execute the installer. At the time of writing, this is Python 3.6.4. + +2. Make sure that the "Install launcher for all users" and "Add Python to PATH" settings are selected and choose "Customize installation". + + ![image](images/python_windows.jpg){width=62%} + +3. In the next screen "Optional Features", you can install everything, but it is essential to install "pip" and "pylauncher (for all users)". Pip is the Python package manager that allows you to install several Python packages and libraries. + +4. In the Advanced Options, make sure that you select "Add Python to environment variables". Also, I suggest that you change the install location to something like C:\\Python36\\ as it will be easier for you to find the Python installation if something goes wrong. + + ![image](images/python_windows2.jpg){width=62%} + +5. Finally, allow Python to use more than 260 characters on the file system by selecting "Disable path length limit" and close the installation dialog. + + ![image](images/python_windows3.jpg){width=62%} + +6. Now, open the command line (cmd) and execute "python" or "python3". If everything was correctly installed, you should see the Python REPL. The REPL (from Read, Evaluate, Print and Loop) is a environment that you can use to program small snippets of Python code. Run *exit()* to leave the REPL. + + ![image](images/python_windows4.jpg){width=62%} + +## Installing on macOS + +You can download the latest macOS binary releases from . Make sure you download the latest Python 3 release (3.6.4 at the time of writing). You can also use Homebrew, a package manager for macOS (). To install the latest Python 3 release with Homebrew, just do "`brew install python3`" on your terminal. Another option is to use the MacPorts package manager () and command "`port install python36`". + +![image](images/python_macos.png){width=62%} + +Finally, open the terminal, execute `python3` and you should see the Python REPL as above. Press Ctrl+D or write `exit()` to leave the REPL. + +## Installing on Linux + +To install Python on Linux, you can download the latest Python 3 source releases from or use your package manager (apt-get, aptitude, synaptic and others) to install it. To make sure you have Python 3 installed on your system, run `python3 --version` in your terminal. + +Finally, open the terminal, execute `python3` and you should see the Python REPL as in the following image. Press Ctrl+D or write `exit()` to leave the REPL. + +![image](images/python_linux.png){width=62%} From efe7851c5448c91cfc7b612e1b3387af4010d2a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 17:51:27 +0100 Subject: [PATCH 27/59] Chapter basic-datatypes --- Makefile | 2 + chapters/basic-datatypes.md | 90 +++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 chapters/basic-datatypes.md diff --git a/Makefile b/Makefile index e27dddf..c0d2f57 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ epub: metadata.yaml \ chapters/introduction.md \ chapters/installation.md \ + chapters/basic-datatypes.md \ pdf: pandoc -o full-speed-python.pdf \ @@ -12,6 +13,7 @@ pdf: -H preamble.tex \ chapters/introduction.md \ chapters/installation.md \ + chapters/basic-datatypes.md \ clean: rm *.epub *.pdf diff --git a/chapters/basic-datatypes.md b/chapters/basic-datatypes.md new file mode 100644 index 0000000..6fa5293 --- /dev/null +++ b/chapters/basic-datatypes.md @@ -0,0 +1,90 @@ +# Numbers and strings + +In this chapter we will work with the most basic datatypes, numbers and strings. Start your Python REPL and write the following: + +```Python +>>> a = 2 +>>> type(a) + +>>> b = 2.5 +>>> type(b) + +``` + +Basically, you are declaring two variables (named "a" and "b") which will hold some numbers: variable "a" is an integer number while variable "b" is a real number. We can now use our variables or any other numbers to do some calculations: + +```Python +>>> a + b +4.5 +>>> (a + b) * 2 +9.0 +>>> 2 + 2 + 4 - 2/3 +7.333333333333333 +``` + +Python also has support for string datatypes. Strings are sequences of characters (like words) and can be defined using single or double quotes: + +```Python +>>> hi = "hello" +>>> hi +'hello' +>>> bye = 'goodbye' +>>> bye +'goodbye' +``` + +You can add strings to concatenate them but you can not mix different datatypes, such as strings and integers. + +```Python +>>> hi + "world" +'helloworld' +>>> "Hello" + 3 +Traceback (most recent call last): + File "", line 1, in +TypeError: must be str, not int +``` + +However, multiplication works as repetition: + +```Python +>>> "Hello" * 3 +'HelloHelloHello' +``` + +## Exercises with numbers + +1. Try the following mathematical calculations and guess what is happening: \((3 / 2)\), \((3 // 2)\), \((3 \% 2)\), \((3**2)\). + + Suggestion: check the Python library reference at . + +2. Calculate the average of the following sequences of numbers: (2, 4), (4, 8, 9), (12, 14/6, 15) + +3. The volume of a sphere is given by (4/3 * pi * r^3). Calculate the volume of a sphere of radius 5. Suggestion: create a variable named "pi" with the value of 3.1415. + +4. Use the module operator (%) to check which of the following numbers is even or odd: (1, 5, 20, 60/7). + + Suggestion: the remainder of \(x/2\) is always zero when \(x\) is even. + +5. Find some values for \(x\) and \(y\) such that \(x < 1/3 < y\) returns "True" on the Python REPL. Suggestion: try \(0 < 1/3 < 1\) on the REPL. + +## Exercises with strings + +Using the Python documentation on strings (), solve the following exercises: + +1. Initialize the string "abc" on a variable named "s": + + 1. Use a function to get the length of the string. + + 2. Write the necessary sequence of operations to transform the string "abc" in "aaabbbccc". Suggestion: Use string concatenation and string indexes. + +2. Initialize the string "aaabbbccc" on a variable named "s": + + 1. Use a function that allows you to find the first occurence of "b" in the string, and the first occurence of "ccc". + + 2. Use a function that allows you to replace all occurences of "a" to "X", and then use the same function to change only the first occurence of "a" to "X". + +3. Starting from the string "aaa bbb ccc", what sequences of operations do you need to arrive at the following strings? You can use the "replace" function. + + 1. "AAA BBB CCC" + + 2. "AAA bbb CCC" From 6b8883ebc75c6bb6ad2940f302145dae8da090d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 17:53:30 +0100 Subject: [PATCH 28/59] Lists chapter --- Makefile | 2 ++ chapters/lists.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 chapters/lists.md diff --git a/Makefile b/Makefile index c0d2f57..c05af75 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ epub: chapters/introduction.md \ chapters/installation.md \ chapters/basic-datatypes.md \ + chapters/lists.md \ pdf: pandoc -o full-speed-python.pdf \ @@ -14,6 +15,7 @@ pdf: chapters/introduction.md \ chapters/installation.md \ chapters/basic-datatypes.md \ + chapters/lists.md \ clean: rm *.epub *.pdf diff --git a/chapters/lists.md b/chapters/lists.md new file mode 100644 index 0000000..1145666 --- /dev/null +++ b/chapters/lists.md @@ -0,0 +1,69 @@ +# Lists + +Python lists are data structures that group sequences of elements. Lists can have elements of several types and you can also mix different types within the same list although all elements are usually of the same datatype. + +Lists are created using square brackets and the elements separated by commas. The elements in a list can be accessed by their positions where 0 is the index of the first element: + + >>> l = [1, 2, 3, 4, 5] + >>> l[0] + 1 + >>> l[1] + 2 + +Can you access the number 4 in the previous list? + +Sometimes you want just a small portion of a list, a sublist. Sublists can be retrieved using a technique called *slicing*, which consists on defining the start and end indexes: + + >>> l = ['a', 'b', 'c', 'd', 'e'] + >>> l[1:3] + ['b', 'c'] + +Finally, arithmetic with lists is also possible, like adding two lists together or repeating the contents of a list. + + >>> [1,2] + [3,4] + [1, 2, 3, 4] + >>> [1,2] * 2 + [1, 2, 1, 2] + +## Exercises with lists + +Create a list named "l" with the following values (\[1, 4, 9, 10, 23\]). Using the Python documentation about lists () solve the following exercises: + +1. Using list slicing get the sublists \[4, 9\] and \[10, 23\]. + +2. Append the value 90 to the end of the list "l". Check the difference between list concatenation and the "append" method. + +3. Calculate the average value of all values on the list. You can use the "sum" and "len" functions. + +4. Remove the sublist \[4, 9\]. + +## List comprehensions + +List comprehensions are a concise way to create lists. It consists of square brackets containing an expression followed by the "for" keyword. The result will be a list whose results match the expression. Here’s how to create a list with the squared numbers of another list. + + >>> [x*x for x in [0, 1, 2, 3]] + [0, 1, 4, 9] + +Given its flexibility, list comprehensions generally make use of the "range" function which returns a range of numbers: + + >>> [x*x for x in range(4)] + [0, 1, 4, 9] + +Sometimes you may want to filter the elements by a given condition. The "if" keyword can be used in those cases: + + >>> [x for x in range(10) if x % 2 == 0] + [0, 2, 4, 6, 8] + +The exemple above returns all even values in range 0..10. More about list comprehensions can be found at . + +## Exercises with list comprehensions + +1. Using list comprehensions, create a list with the squares of the first 10 numbers. + +2. Using list comprehensions, create a list with the cubes of the first 20 numbers. + +3. Create a list comprehension with all the even numbers from 0 to 20, and another one with all the odd numbers. + +4. Create a list with the squares of the even numbers from 0 to 20, and sum the list using the "sum" function. The result should be 1140. First create the list using list comprehensions, check the result, then apply the sum to the list comprehension. + +5. Make a list comprehension that returns a list with the squares of all even numbers from 0 to 20, but ignore those numbers that are divisible by 3. In other words, each number should be divisible by 2 and not divisible by 3. Search for the "and" keyword in the Python documentation. The resulting list is \[4, 16, 64, 100, 196, 256\]. From 27b1ed92ac37708fa1309caa476634fcbbd2d1de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 18:09:40 +0100 Subject: [PATCH 29/59] Rest of chapters as markdown --- Makefile | 12 ++++ chapters/classes.md | 73 +++++++++++++++++++++++ chapters/dictionaries.md | 106 ++++++++++++++++++++++++++++++++++ chapters/functions.md | 113 ++++++++++++++++++++++++++++++++++++ chapters/generators.md | 59 +++++++++++++++++++ chapters/iterators.md | 101 ++++++++++++++++++++++++++++++++ chapters/lists.md | 52 ++++++++++------- chapters/loops.md | 122 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 618 insertions(+), 20 deletions(-) create mode 100644 chapters/classes.md create mode 100644 chapters/dictionaries.md create mode 100644 chapters/functions.md create mode 100644 chapters/generators.md create mode 100644 chapters/iterators.md create mode 100644 chapters/loops.md diff --git a/Makefile b/Makefile index c05af75..309db20 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,12 @@ epub: chapters/installation.md \ chapters/basic-datatypes.md \ chapters/lists.md \ + chapters/functions.md \ + chapters/loops.md \ + chapters/dictionaries.md \ + chapters/classes.md \ + chapters/iterators.md \ + chapters/generators.md \ pdf: pandoc -o full-speed-python.pdf \ @@ -16,6 +22,12 @@ pdf: chapters/installation.md \ chapters/basic-datatypes.md \ chapters/lists.md \ + chapters/functions.md \ + chapters/loops.md \ + chapters/dictionaries.md \ + chapters/classes.md \ + chapters/iterators.md \ + chapters/generators.md \ clean: rm *.epub *.pdf diff --git a/chapters/classes.md b/chapters/classes.md new file mode 100644 index 0000000..4cd7233 --- /dev/null +++ b/chapters/classes.md @@ -0,0 +1,73 @@ +# Classes + +In object oriented programming (OOP), a class is a structure that allows to group together a set of properties (called attributes) and functions (called methods) to manipulate those properties. Take the following class that defines a person with properties "name" and "age" and the "greet" method. + +```Python +class Person: + + def __init__(self, name, age): + self.name = name + self.age = age + + def greet(self): + print("Hello, my name is %s!" % self.name) +``` + +Most classes will need the constructor method ("\_\_init\_\_") to initialize the class’s attributes. In the previous case the constructor of the class receives the person’s name and age and stores that information in the class’s instance (referenced by the *self* keyword). Finally, "greet" method prints the name of the person as stored in a specific class instance (object). + +Class instances are used through the instantiation of objects. Here’s how we can instantiate two objects: + +```Python +>>> a = Person("Peter", 20) +>>> b = Person("Anna", 19) + +>>> a.greet() +Hello, my name is Peter! +>>> b.greet() +Hello, my name is Anna! + +>>> print(a.age) # We can also access the attributes of an object +20 +``` + +## Exercises with classes + +Use the Python documentation on classes at to solve the following exercises. + +1. Implement a class named "Rectangle" to store the coordinates of a rectangle given by (x1, y1) and (x2, y2). + +2. Implement the class constructor with the parameters (x1, y1, x2, y2) and store them in the class instances using the "self" keyword. + +3. Implement the "width()" and "height()" methods which return, respectively, the width and height of a rectangle. Create two objects, instances of "Rectangle" to test the calculations. + +4. Implement the method "area" to return the area of the rectangle (width\*height). + +5. Implement the method "circumference" to return the perimeter of the rectangle (2\*width + 2\*height). + +6. Do a print of one of the objects created to test the class. Implement the "\_\_str\_\_" method such that when you print one of the objects it print the coordinates as (x1, y1)(x2, y2). + +## Class inheritance + +In object oriented programming, inheritance is one of the forms in which a subclass can inherit the attributes and methods of another class, allowing it to rewrite some of the super class’s functionalities. For instance, from the "Person" class above we could create a subclass to keep people with 10 years of age: + +```Python +class TenYearOldPerson(Person): + + def __init__(self, name): + super().__init__(name, 10) + + def greet(self): + print("I don't talk to strangers!!") +``` + +The indication that the "TenYearOldPerson" class is a subclass of "Person" is given on the first line. Then, we rewrote the constructor of the subclass to only receive the name of the person, but we will eventually call the super class’s constructor with the name of the 10-year-old and the age hardcoded as 10. Finally we reimplemented the "greet" method. + +## Exercises with inheritance + +Use the "Rectangle" class as implemented above for the following exercises: + +1. Create a "Square" class as subclass of "Rectangle". + +2. Implement the "Square" constructor. The constructor should have only the x1, y1 coordinates and the size of the square. Notice which arguments you’ll have to use when you invoke the "Rectangle" constructor when you use "super". + +3. Instantiate two objects of "Square", invoke the area method and print the objects. Make sure that all calculations are returning correct numbers and that the coordinates of the squares are consistent with the size of the square used as argument. diff --git a/chapters/dictionaries.md b/chapters/dictionaries.md new file mode 100644 index 0000000..1738237 --- /dev/null +++ b/chapters/dictionaries.md @@ -0,0 +1,106 @@ +# Dictionaries + +In this chapter we will work with Python dictionaries. Dictionaries are data structures that indexes values by a given key (key-value pairs). The following example shows a dictionary that indexes students ages by name. + +```Python +ages = { + "Peter": 10, + "Isabel": 11, + "Anna": 9, + "Thomas": 10, + "Bob": 10, + "Joseph": 11, + "Maria": 12, + "Gabriel": 10, +} + +>>> print(ages["Peter"]) +10 +``` + +It is possible to iterate over the contents of a dictionary using "items", like this: + +```Python +>>> for name, age in ages.items(): +... print(name, age) +... +Peter 10 +Isabel 11 +Anna 9 +Thomas 10 +Bob 10 +Joseph 11 +Maria 12 +Gabriel 10 +``` + +However, dictionary keys don’t necessarily need to be strings but can be any [immutable](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) object: + +```Python +d = { + 0: [0, 0, 0], + 1: [1, 1, 1], + 2: [2, 2, 2], +} + +>>> d[2] +[2, 2, 2] +``` + +And you can also use other dictionaries as values: + +```Python +students = { + "Peter": {"age": 10, "address": "Lisbon"}, + "Isabel": {"age": 11, "address": "Sesimbra"}, + "Anna": {"age": 9, "address": "Lisbon"}, +} + +>>> students['Peter'] +{'age': 10, 'address': 'Lisbon'} +>>> students['Peter']['address'] +'Lisbon' +``` + +This is quite useful to structure hierarchical information. + +## Exercises with dictionaries + +Use the Python documentation at to solve the following exercises. + +Take the following Python dictionary: + + ages = { + "Peter": 10, + "Isabel": 11, + "Anna": 9, + "Thomas": 10, + "Bob": 10, + "Joseph": 11, + "Maria": 12, + "Gabriel": 10, + } + +1. How many students are in the dictionary? Search for the "len" function. + +2. Implement a function that receives the "ages" dictionary as parameter and returns the average age of the students. Traverse all items on the dictionary using the "items" method as above. + +3. Implement a function that receives the "ages" dictionary as parameter and returns the name of the oldest student. + +4. Implement a function that receives the "ages" dictionary and a number "n" and returns a new dict where each student is \(n\) years older. For instance, *new_ages(ages, 10)* returns a copy of "ages" where each student is 10 years older. + +## Exercises with sub-dictionaries + +Take the following dictionary: + + students = { + "Peter": {"age": 10, "address": "Lisbon"}, + "Isabel": {"age": 11, "address": "Sesimbra"}, + "Anna": {"age": 9, "address": "Lisbon"}, + } + +1. How many students are in the "students" dict? Use the appropriate function. + +2. Implement a function that receives the students dict and returns the average age. + +3. Implement a function that receives the students dict and an address, and returns a list with names of all students whose address matches the address in the argument. For instance, invoking "find_students(students, ’Lisbon’)" should return Peter and Anna. diff --git a/chapters/functions.md b/chapters/functions.md new file mode 100644 index 0000000..ec14de3 --- /dev/null +++ b/chapters/functions.md @@ -0,0 +1,113 @@ +# Modules and functions + +In this chapter we will talk about modules and functions. A function is a block of code that is used to perform a single action. A module is a Python file containing variables, functions and many more things. + +Start up your Python REPL and let’s use the "math" module which provides access to mathematical functions: + +```Python +>>> import math +>>> math.cos(0.0) +1.0 +>>> math.radians(275) +4.799655442984406 +``` + +Functions are sequences of instructions that are executed when the function is invoked. The following defines the "do\_hello" function that prints two messages when invoked: + +```Python +>>> def do_hello(): +... print("Hello") +... print("World") +... +>>> do_hello() +Hello +World +``` + +Make sure that you insert a tab before both print expressions in the previous function. Tabs and spaces in Python are relevant and define that a block of code is somewhat dependent on a previous instruction. For instance, the print expressions are "inside" the "do\_hello" function therefore must have a tab. + +Functions can also receive parameters a return values (using the "return" keyword): + +```Python +>>> def add_one(val): +... print("Function got value", val) +... return val + 1 +... +>>> value = add_one(1) +Function got value 1 +>>> value +2 +``` + +## Exercises with the math module + +Use the Python documentation about the math module () to solve the following exercises: + +1. Find the greatest common divisor of the following pairs of numbers: (15, 21), (152, 200), (1988, 9765). + +2. Compute the base-2 logarithm of the following numbers: 0, 1, 2, 6, 9, 15. + +3. Use the "input" function to ask the user for a number and show the result of the sine, cosine and tangent of the number. Make sure that you convert the user input from string to a number (use the int() or the float() function). + +## Exercises with functions + +1. Implement the "add2" function that receives two numbers as arguments and returns the sum of the numbers. Then implement the "add3" function that receives and sums 3 parameters. + +2. Implement a function that returns the greatest of two numbers given as parameters. Use the "if" statement to compare both numbers: . + +3. Implement a function named "is\_divisible" that receives two parameters (named "a" and "b") and returns true if "a" can be divided by "b" or false otherwise. A number is divisible by another when the remainder of the division is zero. Use the modulo operator ("%"). + +4. Create a function named "average" that computes the average value of a list passed as parameter to the function. Use the "sum" and "len" functions. + +## Recursive functions + +In computer programming, a recursive function is simply a function that calls itself. For instance take the factorial function. + +\begin{equation} +f(x)=\begin{cases} + 1, & \text{if $x=0$}.\\ + x \times f(x-1), & \text{otherwise}. +\end{cases} +\end{equation} + +As an example, take the factorial of 5: + +\begin{equation} +\begin{split} +5! &= 5 \times 4! \\ + &= 5 \times 4 \times 3! \\ + &= 5 \times 4 \times 3 \times 2! \\ + &= 5 \times 4 \times 3 \times 2 \times 1 \\ + &= 120 +\end{split} +\end{equation} + +Basically, the factorial of 5 is 5 times the factorial of 4, etc. Finally, the factorial of 1 (or of zero) is 1 which breaks the recursion. In Python we could write the following recursive function: + +```Python +def factorial(x): + if x == 0: + return 1 + else: + return x * factorial(x-1) +``` + +The trick with recursive functions is that there must be a "base" case where the recursion must end and a recursive case that iterates towards the base case. In the case of factorial we know that the factorial of zero is one, and the factorial of a number greater that zero will depend on the factorial of the previous number until it reaches zero. + +## Exercises with recursive functions + +1. Implement the factorial function and test it with several different values. Cross-check with a calculator. + +2. Implement a recursive function to compute the sum of the \(n\) first integer numbers (where \(n\) is a function parameter). Start by thinking about the base case (the sum of the first 0 integers is?) and then think about the recursive case. + +3. The Fibonnaci sequence is a sequence of numbers in which each number of the sequence matches the sum of the previous two terms. Given the following recursive definition implement \(fib(n)\). + + \begin{equation} + fib(n)=\begin{cases} + 0, & \text{if $x=0$}.\\ + 1, & \text{if $x=1$}.\\ + fib(n-1) + fib(n-2), & \text{otherwise}. + \end{cases} + \end{equation} + + Check your results for the first numbers of the sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... diff --git a/chapters/generators.md b/chapters/generators.md new file mode 100644 index 0000000..62ed3a8 --- /dev/null +++ b/chapters/generators.md @@ -0,0 +1,59 @@ +# Generators + +If you read the previous chapter, you know that iterators are objects that are regularly used with "for" loops. In other others, iterators are objects that implement the iteration protocol. A Python generator is a convenient way to implement an iterator. Instead of a class, a generator is a function which returns a value each time the "yield" keyword is used. Here’s an example of a generator to count the values between two numbers: + +```Python +def myrange(a, b): + while a < b: + yield a + a += 1 +``` + +Like iterators, generators can be used with the "for" loop: + +```Python +>>> for value in myrange(1, 4): +... print(value) +... +1 +2 +3 +``` + +Under the hood, generators behave similarly to iterators: + +```Python +>>> seq = myrange(1,3) +>>> next(seq) +1 +>>> next(seq) +2 +>>> next(seq) +Traceback (most recent call last): + File "", line 1, in +StopIteration +``` + +The interesting thing about generators is the "yield" keyword. The "yield" keyword works much like the "return" keyword, but unlike "return", it allows the function to eventually resume its execution. In other words, each time the next value of a generator is needed, Python wakes up the function and resumes its execution from the "yield" line as if the function had never exited. + +Generator functions can use other functions inside. For instance, it is very common to use the "range" function to iterate over a sequence of numbers: + +```Python +def squares(n): + for value in range(n): + yield value * value +``` + +## Exercises with generators + +1. Implement a generator called "squares" to yield the square of all numbers from \(a\) to \(b\). Test it with a "for" loop and print each of the yielded values. + +2. Create a generator to yield all the even numbers from 1 to \(n\). + +3. Create another generator to yield all the odd numbers from 1 to \(n\). + +4. Implement a generator that returns all numbers from \(n\) down to 0. + +5. Create a generator to return the fibonnaci sequence starting from the first element up to \(n\). The first numbers of the sequence are: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... + +6. Implement a generator that returns all consecutive pairs of numbers from 0 to \(n\), such as (0, 1), (1, 2), (2, 3)... diff --git a/chapters/iterators.md b/chapters/iterators.md new file mode 100644 index 0000000..5344ddb --- /dev/null +++ b/chapters/iterators.md @@ -0,0 +1,101 @@ +# Iterators + +As we saw previously, in Python we use the "for" loop to iterate over the contents of objects: + +```Python +>>> for value in [0, 1, 2, 3, 4, 5]: +... print(value) +... +0 +1 +4 +9 +16 +25 +``` + +Objects that can be used with a "for" loop are called iterators. An iterator is, therefore, an object that follows the iteration protocol. + +The built-in function "iter" can be used to build iterator objects, while the "next" function can be used to gradually iterate over their content: + +```Python +>>> my_iter = iter([1, 2, 3]) +>>> my_iter + +>>> next(my_iter) +1 +>>> next(my_iter) +2 +>>> next(my_iter) +3 +>>> next(my_iter) +Traceback (most recent call last): + File "", line 1, in +StopIteration +``` + +If there are no more elements, the iterator raises a "StopIteration" exception. + +## Iterator classes + +Iterators can be implemented as classes. You just need to implement the "\_\_next\_\_" and "\_\_iter\_\_" methods. Here’s an example of a class that mimics the "range" function, returning all values from "a" to "b": + +```Python +class MyRange: + + def __init__(self, a, b): + self.a = a + self.b = b + + def __iter__(self): + return self + + def __next__(self): + if self.a < self.b: + value = self.a + self.a += 1 + return value + else: + raise StopIteration +``` + +Basically, on every call to "next" it moves forward the internal variable "a" and returns its value. When it reaches "b", it raises the StopIteration exception. + +```Python +>>> myrange = MyRange(1, 4) +>>> next(myrange) +1 +>>> next(myrange) +2 +>>> next(myrange) +3 +>>> next(myrange) +Traceback (most recent call last): + File "", line 1, in +StopIteration +``` + +But most important, you can use the iterator class in a "for" loop: + +```Python +>>> for value in MyRange(1, 4): +... print(value) +... +1 +2 +3 +``` + +## Exercises with iterators + +1. Implement an iterator class to return the square of all numbers from "a" to "b". + +2. Implement an iterator class to return all the even numbers from 1 to \(n\). + +3. Implement an iterator class to return all the odd numbers from 1 to \(n\). + +4. Implement an iterator class to return all numbers from \(n\) down to 0. + +5. Implement an iterator class to return the fibonnaci sequence from the first element up to \(n\). You can check the definition of the fibonnaci sequence in the function’s chapter. These are the first numbers of the sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... + +6. Implement an iterator class to return all consecutive pairs of numbers from 0 until \(n\), such as (0, 1), (1, 2), (2, 3)... diff --git a/chapters/lists.md b/chapters/lists.md index 1145666..397088b 100644 --- a/chapters/lists.md +++ b/chapters/lists.md @@ -4,30 +4,36 @@ Python lists are data structures that group sequences of elements. Lists can hav Lists are created using square brackets and the elements separated by commas. The elements in a list can be accessed by their positions where 0 is the index of the first element: - >>> l = [1, 2, 3, 4, 5] - >>> l[0] - 1 - >>> l[1] - 2 +```Python +>>> l = [1, 2, 3, 4, 5] +>>> l[0] +1 +>>> l[1] +2 +``` Can you access the number 4 in the previous list? Sometimes you want just a small portion of a list, a sublist. Sublists can be retrieved using a technique called *slicing*, which consists on defining the start and end indexes: - >>> l = ['a', 'b', 'c', 'd', 'e'] - >>> l[1:3] - ['b', 'c'] +```Python +>>> l = ['a', 'b', 'c', 'd', 'e'] +>>> l[1:3] +['b', 'c'] +``` Finally, arithmetic with lists is also possible, like adding two lists together or repeating the contents of a list. - >>> [1,2] + [3,4] - [1, 2, 3, 4] - >>> [1,2] * 2 - [1, 2, 1, 2] +```Python +>>> [1,2] + [3,4] +[1, 2, 3, 4] +>>> [1,2] * 2 +[1, 2, 1, 2] +``` ## Exercises with lists -Create a list named "l" with the following values (\[1, 4, 9, 10, 23\]). Using the Python documentation about lists () solve the following exercises: +Create a list named "l" with the following values ([1, 4, 9, 10, 23]). Using the Python documentation about lists () solve the following exercises: 1. Using list slicing get the sublists \[4, 9\] and \[10, 23\]. @@ -35,24 +41,30 @@ Create a list named "l" with the following values (\[1, 4, 9, 10, 23\]). Using t 3. Calculate the average value of all values on the list. You can use the "sum" and "len" functions. -4. Remove the sublist \[4, 9\]. +4. Remove the sublist [4, 9]. ## List comprehensions List comprehensions are a concise way to create lists. It consists of square brackets containing an expression followed by the "for" keyword. The result will be a list whose results match the expression. Here’s how to create a list with the squared numbers of another list. - >>> [x*x for x in [0, 1, 2, 3]] - [0, 1, 4, 9] +```Python +>>> [x*x for x in [0, 1, 2, 3]] +[0, 1, 4, 9] +``` Given its flexibility, list comprehensions generally make use of the "range" function which returns a range of numbers: - >>> [x*x for x in range(4)] - [0, 1, 4, 9] +```Python +>>> [x*x for x in range(4)] +[0, 1, 4, 9] +``` Sometimes you may want to filter the elements by a given condition. The "if" keyword can be used in those cases: - >>> [x for x in range(10) if x % 2 == 0] - [0, 2, 4, 6, 8] +```Python +>>> [x for x in range(10) if x % 2 == 0] +[0, 2, 4, 6, 8] +``` The exemple above returns all even values in range 0..10. More about list comprehensions can be found at . diff --git a/chapters/loops.md b/chapters/loops.md new file mode 100644 index 0000000..187d28b --- /dev/null +++ b/chapters/loops.md @@ -0,0 +1,122 @@ +# Iteration and loops + +In this chapter we are going to explore the topics of iteration and loops. Loops are used in computer programming to automate repetitive tasks. + +In Python the most common form of iteration is the "for" loop. The "for" loop allows you to iterate over all items of a list such that you can do whatever you want with each item. For instance, let’s create a list and print the square value of each element. + +```Python +>>> for value in [0, 1, 2, 3, 4, 5]: +... print(value * value) +... +0 +1 +4 +9 +16 +25 +``` + +It’s quite easy but very powerful\! The "for" loop is the basis of many things in programming. For instance, you already know about the "sum(list)" function which sums all the elements of a list, but here’s an example using the "for" loop: + +```Python +>>> mylist = [1,5,7] +>>> sum = 0 +>>> for value in mylist: +... sum = sum + value +... +>>> print(sum) +13 +``` + +Basically, you create the variable "sum" and keep adding each value as it comes from the list. + +Sometimes, instead of the values of a list, you may need to work with the indexes themselves, i.e., not with the values, but the positions where they are in the list. Here’s an example that iterates over a list and returns the indexes and the values for each index: + +```Python +>>> mylist = [1,5,7] +>>> for i in range(len(mylist)): +... print("Index:", i, "Value:", mylist[i]) +... +Index: 0 Value: 1 +Index: 1 Value: 5 +Index: 2 Value: 7 +``` + +You can see that we are not iterating over the list itself but iterating over the "range" of the length of the list. The range function returns a special list: + +```Python +>>> list(range(3)) +[0, 1, 2] +``` + +So, when you use "range" you are not iterating over "mylist" but over a list with some numbers that you’ll use as indexes to access individual values on "mylist". More about the range function in the Python docs at . + +Sometimes you may need both things (indexes and values), and you can use the "enumerate" function: + +```Python +>>> mylist = [1,5,7] +>>> for i, value in enumerate(mylist): +... print("Index:", i, "Value:", value) +... +Index: 0 Value: 1 +Index: 1 Value: 5 +Index: 2 Value: 7 +``` + +Remember that the first value on a Python list is always at index 0. + +Finally, we also have the "while" statement that allows us to repeat a sequence of instructions while a specified condition is true. For instance, the following example starts "n" at 10 and **while "n" is greater than 0**, it keeps subtracting 1 from "n". When "n" reaches 0, the condition "n \> 0" is false, and the loop ends: + +```Python +>>> n = 10 +>>> while n > 0: +... print(n) +... n = n-1 +... +10 +9 +8 +7 +6 +5 +4 +3 +2 +1 +``` + +Notice that it never prints 0... + +## Exercises with the for loop + +For this section you may want to consult the Python docs at . + +1. Create a function "add" that receives a list as parameter and returns the sum of all elements in the list. Use the "for" loop to iterate over the elements of the list. + +2. Create a function that receives a list as parameter and returns the maximum value in the list. As you iterate over the list you may want to keep the maximum value found so far in order to keep comparing it with the next elements of the list. + +3. Modify the previous function such that it returns a list with the first element being the maximum value and the second being the index of the maximum value in the list. Besides keeping the maximum value found so far, you also need to keep the position where it occurred. + +4. Implement a function that returns the reverse of a list received as parameter. You may create an empty list and keep adding the values in reversed order as they come from the original list. Check what you can do with lists at . + +5. Make the function "is\_sorted" that receives a list as parameter and returns True if the list is sorted in ascending order. For instance \[1, 2, 2, 3\] is ordered while \[1, 2, 3, 2\] is not. Suggestion: you have to compare a number in the list with the next one, so you can use indexes or you need to keep the previous number in a variable as you iterate over the list. + +6. Implement the function "is\_sorted\_dec" which is similar to the previous one but all items must be sorted by decreasing order. + +7. Implement the "has\_duplicates" function which verifies if a list has duplicate values. You may have to use two "for" loops, where for each value you have to check for duplicates on the rest of the list. + +## Exercises with the while statement + +1. Implement a function that receives a number as parameter and prints, in decreasing order, which numbers are even and which are odd, until it reaches 0. + + >>> even_odd(10) + Even number: 10 + Odd number: 9 + Even number: 8 + Odd number: 7 + Even number: 6 + Odd number: 5 + Even number: 4 + Odd number: 3 + Even number: 2 + Odd number: 1 From c5fdac43928defa92da7c803b0741e15f90b708e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 18:10:20 +0100 Subject: [PATCH 30/59] Remove tex files --- chapters/basic-datatypes.tex | 99 -------------------------- chapters/classes.tex | 81 --------------------- chapters/dictionaries.tex | 118 ------------------------------- chapters/functions.tex | 125 -------------------------------- chapters/generators.tex | 66 ----------------- chapters/installation.tex | 64 ----------------- chapters/introduction.tex | 13 ---- chapters/iterators.tex | 106 ---------------------------- chapters/lists.tex | 91 ------------------------ chapters/loops.tex | 133 ----------------------------------- full-speed-python.tex | 66 ----------------- 11 files changed, 962 deletions(-) delete mode 100644 chapters/basic-datatypes.tex delete mode 100644 chapters/classes.tex delete mode 100644 chapters/dictionaries.tex delete mode 100644 chapters/functions.tex delete mode 100644 chapters/generators.tex delete mode 100644 chapters/installation.tex delete mode 100644 chapters/introduction.tex delete mode 100644 chapters/iterators.tex delete mode 100644 chapters/lists.tex delete mode 100644 chapters/loops.tex delete mode 100644 full-speed-python.tex diff --git a/chapters/basic-datatypes.tex b/chapters/basic-datatypes.tex deleted file mode 100644 index 7982817..0000000 --- a/chapters/basic-datatypes.tex +++ /dev/null @@ -1,99 +0,0 @@ -\chapter{Numbers and strings}\label{basic-datatypes} - -In this chapter we will work with the most basic datatypes, numbers and strings. Start your Python REPL and write the following: - -\begin{lstlisting} ->>> a = 2 ->>> type(a) - ->>> b = 2.5 ->>> type(b) - -\end{lstlisting} - -Basically, you are declaring two variables (named "a" and "b") which will hold some numbers: variable "a" is an integer number while variable "b" is a real number. We can now use our variables or any other numbers to do some calculations: - -\begin{lstlisting} ->>> a + b -4.5 ->>> (a + b) * 2 -9.0 ->>> 2 + 2 + 4 - 2/3 -7.333333333333333 -\end{lstlisting} - -Python also has support for string datatypes. Strings are sequences of characters (like words) and can be defined using single or double quotes: - -\begin{lstlisting} ->>> hi = "hello" ->>> hi -'hello' ->>> bye = 'goodbye' ->>> bye -'goodbye' -\end{lstlisting} - -You can add strings to concatenate them but you can not mix different datatypes, such as strings and integers. - -\begin{lstlisting} ->>> hi + "world" -'helloworld' ->>> "Hello" + 3 -Traceback (most recent call last): - File "", line 1, in -TypeError: must be str, not int -\end{lstlisting} - -However, multiplication works as repetition: - -\begin{lstlisting} ->>> "Hello" * 3 -'HelloHelloHello' -\end{lstlisting} - - -\section{Exercises with numbers} - -\begin{enumerate} - -\item Try the following mathematical calculations and guess what is happening: $(3 / 2)$, $(3 // 2)$, $(3 \% 2)$, $(3**2)$. - -Suggestion: check the Python library reference at \url{https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex}. - -\item Calculate the average of the following sequences of numbers: (2, 4), (4, 8, 9), (12, 14/6, 15) - -\item The volume of a sphere is given by $4/3\pi r^3$. Calculate the volume of a sphere of radius 5. Suggestion: create a variable named "pi" with the value of 3.1415. - -\item Use the module operator (\%) to check which of the following numbers is even or odd: (1, 5, 20, 60/7). - -Suggestion: the remainder of $x/2$ is always zero when $x$ is even. - -\item Find some values for $x$ and $y$ such that $x < 1/3 < y$ returns "True" on the Python REPL. Suggestion: try $0 < 1/3 < 1$ on the REPL. - -\end{enumerate} - -\section{Exercises with strings} - -Using the Python documentation on strings (\url{https://docs.python.org/3/library/stdtypes.html?#text-sequence-type-str}), solve the following exercises: - -\begin{enumerate} - -\item Initialize the string "abc" on a variable named "s": -\begin{enumerate} -\item Use a function to get the length of the string. -\item Write the necessary sequence of operations to transform the string "abc" in "aaabbbccc". Suggestion: Use string concatenation and string indexes. -\end{enumerate} - -\item Initialize the string "aaabbbccc" on a variable named "s": -\begin{enumerate} -\item Use a function that allows you to find the first occurence of "b" in the string, and the first occurence of "ccc". -\item Use a function that allows you to replace all occurences of "a" to "X", and then use the same function to change only the first occurence of "a" to "X". -\end{enumerate} - -\item Starting from the string "aaa bbb ccc", what sequences of operations do you need to arrive at the following strings? You can use the "replace" function. -\begin{enumerate} -\item "AAA BBB CCC" -\item "AAA bbb CCC" -\end{enumerate} - -\end{enumerate} diff --git a/chapters/classes.tex b/chapters/classes.tex deleted file mode 100644 index 818569f..0000000 --- a/chapters/classes.tex +++ /dev/null @@ -1,81 +0,0 @@ -\chapter{Classes}\label{classes} - -In object oriented programming (OOP), a class is a structure that allows to group together a set of properties (called attributes) and functions (called methods) to manipulate those properties. Take the following class that defines a person with properties "name" and "age" and the "greet" method. - -\begin{lstlisting} -class Person: - - def __init__(self, name, age): - self.name = name - self.age = age - - def greet(self): - print("Hello, my name is %s!" % self.name) -\end{lstlisting} - -Most classes will need the constructor method ("\_\_init\_\_") to initialize the class's attributes. In the previous case the constructor of the class receives the person's name and age and stores that information in the class's instance (referenced by the \textit{self} keyword). Finally, "greet" method prints the name of the person as stored in a specific class instance (object). - -Class instances are used through the instantiation of objects. Here's how we can instantiate two objects: - -\begin{lstlisting} ->>> a = Person("Peter", 20) ->>> b = Person("Anna", 19) - ->>> a.greet() -Hello, my name is Peter! ->>> b.greet() -Hello, my name is Anna! - ->>> print(a.age) # We can also access the attributes of an object -20 -\end{lstlisting} - -\section{Exercises with classes} - -Use the Python documentation on classes at \url{https://docs.python.org/3/tutorial/classes.html} to solve the following exercises. - -\begin{enumerate} - -\item Implement a class named "Rectangle" to store the coordinates of a rectangle given by (x1, y1) and (x2, y2). - -\item Implement the class constructor with the parameters (x1, y1, x2, y2) and store them in the class instances using the "self" keyword. - -\item Implement the "width()" and "height()" methods which return, respectively, the width and height of a rectangle. Create two objects, instances of "Rectangle" to test the calculations. - -\item Implement the method "area" to return the area of the rectangle (width*height). - -\item Implement the method "circumference" to return the perimeter of the rectangle (2*width + 2*height). - -\item Do a print of one of the objects created to test the class. Implement the "\_\_str\_\_" method such that when you print one of the objects it print the coordinates as (x1, y1)(x2, y2). - -\end{enumerate} - -\section{Class inheritance} - -In object oriented programming, inheritance is one of the forms in which a subclass can inherit the attributes and methods of another class, allowing it to rewrite some of the super class's functionalities. For instance, from the "Person" class above we could create a subclass to keep people with 10 years of age: - -\begin{lstlisting} -class TenYearOldPerson(Person): - - def __init__(self, name): - super().__init__(name, 10) - - def greet(self): - print("I don't talk to strangers!!") -\end{lstlisting} - -The indication that the "TenYearOldPerson" class is a subclass of "Person" is given on the first line. Then, we rewrote the constructor of the subclass to only receive the name of the person, but we will eventually call the super class's constructor with the name of the 10-year-old and the age hardcoded as 10. Finally we reimplemented the "greet" method. - -\section{Exercises with inheritance} - -Use the "Rectangle" class as implemented above for the following exercises: - -\begin{enumerate} - -\item Create a "Square" class as subclass of "Rectangle". - -\item Implement the "Square" constructor. The constructor should have only the x1, y1 coordinates and the size of the square. Notice which arguments you'll have to use when you invoke the "Rectangle" constructor when you use "super". - -\item Instantiate two objects of "Square", invoke the area method and print the objects. Make sure that all calculations are returning correct numbers and that the coordinates of the squares are consistent with the size of the square used as argument. - -\end{enumerate} diff --git a/chapters/dictionaries.tex b/chapters/dictionaries.tex deleted file mode 100644 index 2ab2efd..0000000 --- a/chapters/dictionaries.tex +++ /dev/null @@ -1,118 +0,0 @@ -\chapter{Dictionaries}\label{dictionaries} - -In this chapter we will work with Python dictionaries. Dictionaries are data structures that indexes values by a given key (key-value pairs). The following example shows a dictionary that indexes students ages by name. - -\begin{lstlisting} -ages = { - "Peter": 10, - "Isabel": 11, - "Anna": 9, - "Thomas": 10, - "Bob": 10, - "Joseph": 11, - "Maria": 12, - "Gabriel": 10, -} - ->>> print(ages["Peter"]) -10 -\end{lstlisting} - -It is possible to iterate over the contents of a dictionary using "items", like this: - -\begin{lstlisting} ->>> for name, age in ages.items(): -... print(name, age) -... -Peter 10 -Isabel 11 -Anna 9 -Thomas 10 -Bob 10 -Joseph 11 -Maria 12 -Gabriel 10 -\end{lstlisting} - -However, dictionary keys don't necessarily need to be strings but can be any \href{https://docs.python.org/3/tutorial/datastructures.html#dictionaries}{immutable} object: - -\begin{lstlisting} -d = { - 0: [0, 0, 0], - 1: [1, 1, 1], - 2: [2, 2, 2], -} - ->>> d[2] -[2, 2, 2] -\end{lstlisting} - -And you can also use other dictionaries as values: - -\begin{lstlisting} -students = { - "Peter": {"age": 10, "address": "Lisbon"}, - "Isabel": {"age": 11, "address": "Sesimbra"}, - "Anna": {"age": 9, "address": "Lisbon"}, -} - ->>> students['Peter'] -{'age': 10, 'address': 'Lisbon'} ->>> students['Peter']['address'] -'Lisbon' -\end{lstlisting} - -This is quite useful to structure hierarchical information. - -\section{Exercises with dictionaries} - -Use the Python documentation at \url{https://docs.python.org/3/library/stdtypes.html#mapping-types-dict} to solve the following exercises. - -Take the following Python dictionary: - -\begin{verbatim} -ages = { - "Peter": 10, - "Isabel": 11, - "Anna": 9, - "Thomas": 10, - "Bob": 10, - "Joseph": 11, - "Maria": 12, - "Gabriel": 10, -} -\end{verbatim} - -\begin{enumerate} - -\item How many students are in the dictionary? Search for the "len" function. - -\item Implement a function that receives the "ages" dictionary as parameter and returns the average age of the students. Traverse all items on the dictionary using the "items" method as above. - -\item Implement a function that receives the "ages" dictionary as parameter and returns the name of the oldest student. - -\item Implement a function that receives the "ages" dictionary and a number "n" and returns a new dict where each student is $n$ years older. For instance, \textit{new\_ages(ages, 10)} returns a copy of "ages" where each student is 10 years older. - -\end{enumerate} - -\section{Exercises with sub-dictionaries} - -Take the following dictionary: - -\begin{verbatim} -students = { - "Peter": {"age": 10, "address": "Lisbon"}, - "Isabel": {"age": 11, "address": "Sesimbra"}, - "Anna": {"age": 9, "address": "Lisbon"}, -} -\end{verbatim} - -\begin{enumerate} - -\item How many students are in the "students" dict? Use the appropriate function. - -\item Implement a function that receives the students dict and returns the average age. - -\item Implement a function that receives the students dict and an address, and returns a list with names of all students whose address matches the address in the argument. For instance, invoking "find\_students(students, 'Lisbon')" should return Peter and Anna. - -\end{enumerate} diff --git a/chapters/functions.tex b/chapters/functions.tex deleted file mode 100644 index 496aa7c..0000000 --- a/chapters/functions.tex +++ /dev/null @@ -1,125 +0,0 @@ -\chapter{Modules and functions}\label{functions} - -In this chapter we will talk about modules and functions. A function is a block of code that is used to perform a single action. A module is a Python file containing variables, functions and many more things. - -Start up your Python REPL and let's use the "math" module which provides access to mathematical functions: - -\begin{lstlisting} ->>> import math ->>> math.cos(0.0) -1.0 ->>> math.radians(275) -4.799655442984406 -\end{lstlisting} - -Functions are sequences of instructions that are executed when the function is invoked. The following defines the "do\_hello" function that prints two messages when invoked: - -\begin{lstlisting} ->>> def do_hello(): -... print("Hello") -... print("World") -... ->>> do_hello() -Hello -World -\end{lstlisting} - -Make sure that you insert a tab before both print expressions in the previous function. Tabs and spaces in Python are relevant and define that a block of code is somewhat dependent on a previous instruction. For instance, the print expressions are "inside" the "do\_hello" function therefore must have a tab. - -Functions can also receive parameters a return values (using the "return" keyword): - -\begin{lstlisting} ->>> def add_one(val): -... print("Function got value", val) -... return val + 1 -... ->>> value = add_one(1) -Function got value 1 ->>> value -2 -\end{lstlisting} - -\section{Exercises with the math module} - -Use the Python documentation about the math module (\url{https://docs.python.org/3/library/math.html}) to solve the following exercises: - -\begin{enumerate} - -\item Find the greatest common divisor of the following pairs of numbers: (15, 21), (152, 200), (1988, 9765). - -\item Compute the base-2 logarithm of the following numbers: 0, 1, 2, 6, 9, 15. - -\item Use the "input" function to ask the user for a number and show the result of the sine, cosine and tangent of the number. Make sure that you convert the user input from string to a number (use the int() or the float() function). - -\end{enumerate} - -\section{Exercises with functions} - -\begin{enumerate} - -\item Implement the "add2" function that receives two numbers as arguments and returns the sum of the numbers. Then implement the "add3" function that receives and sums 3 parameters. - -\item Implement a function that returns the greatest of two numbers given as parameters. Use the "if" statement to compare both numbers: \url{https://docs.python.org/3/tutorial/controlflow.html#if-statements}. - -\item Implement a function named "is\_divisible" that receives two parameters (named "a" and "b") and returns true if "a" can be divided by "b" or false otherwise. A number is divisible by another when the remainder of the division is zero. Use the modulo operator ("\%"). - -\item Create a function named "average" that computes the average value of a list passed as parameter to the function. Use the "sum" and "len" functions. - -\end{enumerate} - -\section{Recursive functions} - -In computer programming, a recursive function is simply a function that calls itself. For instance take the factorial function. - -\begin{equation} -f(x)=\begin{cases} - 1, & \text{if $x=0$}.\\ - x \times f(x-1), & \text{otherwise}. -\end{cases} -\end{equation} - -As an example, take the factorial of 5: - -\begin{equation} -\begin{split} -5! &= 5 \times 4! \\ - &= 5 \times 4 \times 3! \\ - &= 5 \times 4 \times 3 \times 2! \\ - &= 5 \times 4 \times 3 \times 2 \times 1 \\ - &= 120 -\end{split} -\end{equation} - -Basically, the factorial of 5 is 5 times the factorial of 4, etc. Finally, the factorial of 1 (or of zero) is 1 which breaks the recursion. In Python we could write the following recursive function: - -\begin{lstlisting} -def factorial(x): - if x == 0: - return 1 - else: - return x * factorial(x-1) -\end{lstlisting} - -The trick with recursive functions is that there must be a "base" case where the recursion must end and a recursive case that iterates towards the base case. In the case of factorial we know that the factorial of zero is one, and the factorial of a number greater that zero will depend on the factorial of the previous number until it reaches zero. - -\section{Exercises with recursive functions} - -\begin{enumerate} - -\item Implement the factorial function and test it with several different values. Cross-check with a calculator. - -\item Implement a recursive function to compute the sum of the $n$ first integer numbers (where $n$ is a function parameter). Start by thinking about the base case (the sum of the first 0 integers is?) and then think about the recursive case. - -\item The Fibonnaci sequence is a sequence of numbers in which each number of the sequence matches the sum of the previous two terms. Given the following recursive definition implement $fib(n)$. - -\begin{equation} -fib(n)=\begin{cases} - 0, & \text{if $x=0$}.\\ - 1, & \text{if $x=1$}.\\ - fib(n-1) + fib(n-2), & \text{otherwise}. -\end{cases} -\end{equation} - -Check your results for the first numbers of the sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... - -\end{enumerate} diff --git a/chapters/generators.tex b/chapters/generators.tex deleted file mode 100644 index ec7d493..0000000 --- a/chapters/generators.tex +++ /dev/null @@ -1,66 +0,0 @@ -\chapter{Generators}\label{generators} - -If you read the previous chapter, you know that iterators are objects that are regularly used with "for" loops. In other others, iterators are objects that implement the iteration protocol. A Python generator is a convenient way to implement an iterator. Instead of a class, a generator is a function which returns a value each time the "yield" keyword is used. Here's an example of a generator to count the values between two numbers: - -\begin{lstlisting} -def myrange(a, b): - while a < b: - yield a - a += 1 -\end{lstlisting} - -Like iterators, generators can be used with the "for" loop: - -\begin{lstlisting} ->>> for value in myrange(1, 4): -... print(value) -... -1 -2 -3 -\end{lstlisting} - -Under the hood, generators behave similarly to iterators: - -\begin{lstlisting} ->>> seq = myrange(1,3) ->>> next(seq) -1 ->>> next(seq) -2 ->>> next(seq) -Traceback (most recent call last): - File "", line 1, in -StopIteration -\end{lstlisting} - -The interesting thing about generators is the "yield" keyword. The "yield" keyword works much like the "return" keyword, but unlike "return", it allows the function to eventually resume its execution. In other words, each time the next value of a generator is needed, Python wakes up the function and resumes its execution from the "yield" line as if the function had never exited. - -Generator functions can use other functions inside. For instance, it is very common to use the "range" function to iterate over a sequence of numbers: - -\begin{lstlisting} -def squares(n): - for value in range(n): - yield value * value -\end{lstlisting} - -\section{Exercises with generators} - -\begin{enumerate} - -\item Implement a generator called "squares" to yield the square of all numbers from $a$ to $b$. Test it with a "for" loop and print each of the yielded values. - -\item Create a generator to yield all the even numbers from 1 to $n$. - -\item Create another generator to yield all the odd numbers from 1 to $n$. - -\item Implement a generator that returns all numbers from $n$ down to 0. - -\item Create a generator to return the fibonnaci sequence starting from the first element up to $n$. The first numbers of the sequence are: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... - -\item Implement a generator that returns all consecutive pairs of numbers from 0 to $n$, such as (0, 1), (1, 2), (2, 3)... - -\end{enumerate} - - - diff --git a/chapters/installation.tex b/chapters/installation.tex deleted file mode 100644 index 38ea5ea..0000000 --- a/chapters/installation.tex +++ /dev/null @@ -1,64 +0,0 @@ -\chapter{Installation}\label{installation} - -In this chapter we will install and run the Python interpreter in your local computer. - -\section{Installing on Windows} - -\begin{enumerate} - -\item Download the latest Python 3 release for Windows on \url{https://www.python.org/downloads/windows/} and execute the installer. At the time of writing, this is Python 3.6.4. - -\item Make sure that the "Install launcher for all users" and "Add Python to PATH" settings are selected and choose "Customize installation". - -\begin{figure}[H] - \centering - \includegraphics[width=0.6\textwidth]{images/python_windows.jpg} -\end{figure} - -\item In the next screen "Optional Features", you can install everything, but it is essential to install "pip" and "pylauncher (for all users)". Pip is the Python package manager that allows you to install several Python packages and libraries. - -\item In the Advanced Options, make sure that you select "Add Python to environment variables". Also, I suggest that you change the install location to something like C:{\textbackslash}Python36{\textbackslash} as it will be easier for you to find the Python installation if something goes wrong. - -\begin{figure}[H] - \centering - \includegraphics[width=0.6\textwidth]{images/python_windows2.jpg} -\end{figure} - -\item Finally, allow Python to use more than 260 characters on the file system by selecting "Disable path length limit" and close the installation dialog. - -\begin{figure}[H] - \centering - \includegraphics[width=0.6\textwidth]{images/python_windows3.jpg} -\end{figure} - -\item Now, open the command line (cmd) and execute "python" or "python3". If everything was correctly installed, you should see the Python REPL. The REPL (from Read, Evaluate, Print and Loop) is a environment that you can use to program small snippets of Python code. Execute \textit{exit()} to exit. - -\begin{figure}[H] - \centering - \includegraphics[width=0.62\textwidth]{images/python_windows4.jpg} -\end{figure} - -\end{enumerate} - -\section{Installing on macOS} - -You can download the latest macOS binary releases from \url{https://www.python.org/downloads/mac-osx/}. Make sure you download the latest Python 3 release (3.6.4 at the time of writing). You can also use Homebrew, a package manager for macOS (\url{https://brew.sh/}). To install the latest Python 3 release with Homebrew, just do "\texttt{brew install python3}" on your terminal. Another option is to use the MacPorts package manager (\url{https://www.macports.org/}) and command "\texttt{port install python36}". - - -\begin{figure}[H] - \centering - \includegraphics[width=0.62\textwidth]{images/python_macos.png} -\end{figure} - -Finally, open the terminal, execute $python3$ and you should see the Python REPL as above. Press Ctrl+D or write $exit()$ to leave the REPL. - -\section{Installing on Linux} - -To install Python on Linux, you can download the latest Python 3 source releases from \url{https://www.python.org/downloads/source/} or use your package manager (apt-get, aptitude, synaptic and others) to install it. To make sure you have Python 3 installed on your system, run $python3 --version$ in your terminal. - -Finally, open the terminal, execute $python3$ and you should see the Python REPL as in the following image. Press Ctrl+D or write $exit()$ to leave the REPL. - -\begin{figure}[H] - \centering - \includegraphics[width=0.62\textwidth]{images/python_linux.png} -\end{figure} diff --git a/chapters/introduction.tex b/chapters/introduction.tex deleted file mode 100644 index a84043b..0000000 --- a/chapters/introduction.tex +++ /dev/null @@ -1,13 +0,0 @@ -\chapter{Introduction}\label{introduction} - -This book aims to teach the Python programming language using a practical approach. Its method is quite simple: after a short introduction to each topic, the reader is invited to learn more by solving the proposed exercises. - -These exercises have been used extensively in my web development and distributed computing classes at the Superior School of Technology of Setúbal. With these exercises, most students are up to speed with Python in less than a month. In fact, students of the distributed computing course, taught in the second year of the software engineering degree, become familiar with Python's syntax in two weeks and are able to implement a distributed client-server application with sockets in the third week. - -Please note that this book is a work in progress and, as such, may contain a few spelling errors that may be corrected in the future. However it is made available now as it is so it can be useful to anyone who wants to use it. I sincerely hope you can get something good through it. - -The source of this book is available on github (\url{https://github.com/joaoventura/full-speed-python}). I welcome any pull requests to correct misspellings, suggest new exercises or to provide clarification of the current content. - -All the best, - -João Ventura - Adjunct Professor at the Escola Superior de Tecnologia de Setúbal. diff --git a/chapters/iterators.tex b/chapters/iterators.tex deleted file mode 100644 index 467c18d..0000000 --- a/chapters/iterators.tex +++ /dev/null @@ -1,106 +0,0 @@ -\chapter{Iterators}\label{iterators} - -As we saw previously, in Python we use the "for" loop to iterate over the contents of objects: - -\begin{lstlisting} ->>> for value in [0, 1, 2, 3, 4, 5]: -... print(value) -... -0 -1 -4 -9 -16 -25 -\end{lstlisting} - -Objects that can be used with a "for" loop are called iterators. An iterator is, therefore, an object that follows the iteration protocol. - -The built-in function "iter" can be used to build iterator objects, while the "next" function can be used to gradually iterate over their content: - -\begin{lstlisting} ->>> my_iter = iter([1, 2, 3]) ->>> my_iter - ->>> next(my_iter) -1 ->>> next(my_iter) -2 ->>> next(my_iter) -3 ->>> next(my_iter) -Traceback (most recent call last): - File "", line 1, in -StopIteration -\end{lstlisting} - -If there are no more elements, the iterator raises a "StopIteration" exception. - -\section{Iterator classes} - -Iterators can be implemented as classes. You just need to implement the "\_\_next\_\_" and "\_\_iter\_\_" methods. Here's an example of a class that mimics the "range" function, returning all values from "a" to "b": - -\begin{lstlisting} -class MyRange: - - def __init__(self, a, b): - self.a = a - self.b = b - - def __iter__(self): - return self - - def __next__(self): - if self.a < self.b: - value = self.a - self.a += 1 - return value - else: - raise StopIteration -\end{lstlisting} - -Basically, on every call to "next" it moves forward the internal variable "a" and returns its value. When it reaches "b", it raises the StopIteration exception. - -\begin{lstlisting} ->>> myrange = MyRange(1, 4) ->>> next(myrange) -1 ->>> next(myrange) -2 ->>> next(myrange) -3 ->>> next(myrange) -Traceback (most recent call last): - File "", line 1, in -StopIteration -\end{lstlisting} - -But most important, you can use the iterator class in a "for" loop: - -\begin{lstlisting} ->>> for value in MyRange(1, 4): -... print(value) -... -1 -2 -3 -\end{lstlisting} - - -\section{Exercises with iterators} - -\begin{enumerate} - -\item Implement an iterator class to return the square of all numbers from "a" to "b". - -\item Implement an iterator class to return all the even numbers from 1 to $n$. - -\item Implement an iterator class to return all the odd numbers from 1 to $n$. - -\item Implement an iterator class to return all numbers from $n$ down to 0. - -\item Implement an iterator class to return the fibonnaci sequence from the first element up to $n$. You can check the definition of the fibonnaci sequence in the function's chapter. These are the first numbers of the sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... - -\item Implement an iterator class to return all consecutive pairs of numbers from 0 until $n$, such as (0, 1), (1, 2), (2, 3)... - -\end{enumerate} \ No newline at end of file diff --git a/chapters/lists.tex b/chapters/lists.tex deleted file mode 100644 index 3e4f189..0000000 --- a/chapters/lists.tex +++ /dev/null @@ -1,91 +0,0 @@ -\chapter{Lists}\label{lists} - -Python lists are data structures that group sequences of elements. Lists can have elements of several types and you can also mix different types within the same list although all elements are usually of the same datatype. - -Lists are created using square brackets and the elements separated by commas. The elements in a list can be accessed by their positions where 0 is the index of the first element: - -\begin{lstlisting} ->>> l = [1, 2, 3, 4, 5] ->>> l[0] -1 ->>> l[1] -2 -\end{lstlisting} - -Can you access the number 4 in the previous list? - -Sometimes you want just a small portion of a list, a sublist. Sublists can be retrieved using a technique called \textit{slicing}, which consists on defining the start and end indexes: - -\begin{lstlisting} ->>> l = ['a', 'b', 'c', 'd', 'e'] ->>> l[1:3] -['b', 'c'] -\end{lstlisting} - -Finally, arithmetic with lists is also possible, like adding two lists together or repeating the contents of a list. - -\begin{lstlisting} ->>> [1,2] + [3,4] -[1, 2, 3, 4] ->>> [1,2] * 2 -[1, 2, 1, 2] -\end{lstlisting} - - -\section{Exercises with lists} - -Create a list named "l" with the following values ([1, 4, 9, 10, 23]). Using the Python documentation about lists (\url{https://docs.python.org/3.5/tutorial/introduction.html#lists}) solve the following exercises: - -\begin{enumerate} - -\item Using list slicing get the sublists [4, 9] and [10, 23]. - -\item Append the value 90 to the end of the list "l". Check the difference between list concatenation and the "append" method. - -\item Calculate the average value of all values on the list. You can use the "sum" and "len" functions. - -\item Remove the sublist [4, 9]. - -\end{enumerate} - - -\section{List comprehensions} - -List comprehensions are a concise way to create lists. It consists of square brackets containing an expression followed by the "for" keyword. The result will be a list whose results match the expression. Here's how to create a list with the squared numbers of another list. - -\begin{lstlisting} ->>> [x*x for x in [0, 1, 2, 3]] -[0, 1, 4, 9] -\end{lstlisting} - -Given its flexibility, list comprehensions generally make use of the "range" function which returns a range of numbers: - -\begin{lstlisting} ->>> [x*x for x in range(4)] -[0, 1, 4, 9] -\end{lstlisting} - -Sometimes you may want to filter the elements by a given condition. The "if" keyword can be used in those cases: - -\begin{lstlisting} ->>> [x for x in range(10) if x % 2 == 0] -[0, 2, 4, 6, 8] -\end{lstlisting} - -The exemple above returns all even values in range 0..10. More about list comprehensions can be found at \url{https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions}. - -\section{Exercises with list comprehensions} - -\begin{enumerate} - -\item Using list comprehensions, create a list with the squares of the first 10 numbers. - -\item Using list comprehensions, create a list with the cubes of the first 20 numbers. - -\item Create a list comprehension with all the even numbers from 0 to 20, and another one with all the odd numbers. - -\item Create a list with the squares of the even numbers from 0 to 20, and sum the list using the "sum" function. The result should be 1140. First create the list using list comprehensions, check the result, then apply the sum to the list comprehension. - -\item Make a list comprehension that returns a list with the squares of all even numbers from 0 to 20, but ignore those numbers that are divisible by 3. In other words, each number should be divisible by 2 and not divisible by 3. Search for the "and" keyword in the Python documentation. The resulting list is [4, 16, 64, 100, 196, 256]. - -\end{enumerate} diff --git a/chapters/loops.tex b/chapters/loops.tex deleted file mode 100644 index f76678b..0000000 --- a/chapters/loops.tex +++ /dev/null @@ -1,133 +0,0 @@ -\chapter{Iteration and loops}\label{loops} - -In this chapter we are going to explore the topics of iteration and loops. Loops are used in computer programming to automate repetitive tasks. - -In Python the most common form of iteration is the "for" loop. The "for" loop allows you to iterate over all items of a list such that you can do whatever you want with each item. For instance, let's create a list and print the square value of each element. - -\begin{lstlisting} ->>> for value in [0, 1, 2, 3, 4, 5]: -... print(value * value) -... -0 -1 -4 -9 -16 -25 -\end{lstlisting} - -It's quite easy but very powerful! The "for" loop is the basis of many things in programming. For instance, you already know about the "sum(list)" function which sums all the elements of a list, but here's an example using the "for" loop: - -\begin{lstlisting} ->>> mylist = [1,5,7] ->>> sum = 0 ->>> for value in mylist: -... sum = sum + value -... ->>> print(sum) -13 -\end{lstlisting} - -Basically, you create the variable "sum" and keep adding each value as it comes from the list. - -Sometimes, instead of the values of a list, you may need to work with the indexes themselves, i.e., not with the values, but the positions where they are in the list. Here's an example that iterates over a list and returns the indexes and the values for each index: - -\begin{lstlisting} ->>> mylist = [1,5,7] ->>> for i in range(len(mylist)): -... print("Index:", i, "Value:", mylist[i]) -... -Index: 0 Value: 1 -Index: 1 Value: 5 -Index: 2 Value: 7 -\end{lstlisting} - -You can see that we are not iterating over the list itself but iterating over the "range" of the length of the list. The range function returns a special list: - -\begin{lstlisting} ->>> list(range(3)) -[0, 1, 2] -\end{lstlisting} - -So, when you use "range" you are not iterating over "mylist" but over a list with some numbers that you'll use as indexes to access individual values on "mylist". More about the range function in the Python docs at \url{https://docs.python.org/3/tutorial/controlflow.html#the-range-function}. - -Sometimes you may need both things (indexes and values), and you can use the "enumerate" function: - -\begin{lstlisting} ->>> mylist = [1,5,7] ->>> for i, value in enumerate(mylist): -... print("Index:", i, "Value:", value) -... -Index: 0 Value: 1 -Index: 1 Value: 5 -Index: 2 Value: 7 -\end{lstlisting} - -Remember that the first value on a Python list is always at index 0. - -Finally, we also have the "while" statement that allows us to repeat a sequence of instructions while a specified condition is true. For instance, the following example starts "n" at 10 and \textbf{while "n" is greater than 0}, it keeps subtracting 1 from "n". When "n" reaches 0, the condition "n > 0" is false, and the loop ends: - -\begin{lstlisting} ->>> n = 10 ->>> while n > 0: -... print(n) -... n = n-1 -... -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 -\end{lstlisting} - -Notice that it never prints 0... - -\section{Exercises with the for loop} - -For this section you may want to consult the Python docs at \url{https://docs.python.org/3/tutorial/controlflow.html#for-statements}. - -\begin{enumerate} - -\item Create a function "add" that receives a list as parameter and returns the sum of all elements in the list. Use the "for" loop to iterate over the elements of the list. - -\item Create a function that receives a list as parameter and returns the maximum value in the list. As you iterate over the list you may want to keep the maximum value found so far in order to keep comparing it with the next elements of the list. - -\item Modify the previous function such that it returns a list with the first element being the maximum value and the second being the index of the maximum value in the list. Besides keeping the maximum value found so far, you also need to keep the position where it occurred. - -\item Implement a function that returns the reverse of a list received as parameter. You may create an empty list and keep adding the values in reversed order as they come from the original list. Check what you can do with lists at \url{https://docs.python.org/3/tutorial/datastructures.html#more-on-lists}. - -\item Make the function "is\_sorted" that receives a list as parameter and returns True if the list is sorted in ascending order. For instance [1, 2, 2, 3] is ordered while [1, 2, 3, 2] is not. Suggestion: you have to compare a number in the list with the next one, so you can use indexes or you need to keep the previous number in a variable as you iterate over the list. - -\item Implement the function "is\_sorted\_dec" which is similar to the previous one but all items must be sorted by decreasing order. - -\item Implement the "has\_duplicates" function which verifies if a list has duplicate values. You may have to use two "for" loops, where for each value you have to check for duplicates on the rest of the list. - -\end{enumerate} - - -\section{Exercises with the while statement} - -\begin{enumerate} - -\item Implement a function that receives a number as parameter and prints, in decreasing order, which numbers are even and which are odd, until it reaches 0. - -\begin{lstlisting} ->>> even_odd(10) -Even number: 10 -Odd number: 9 -Even number: 8 -Odd number: 7 -Even number: 6 -Odd number: 5 -Even number: 4 -Odd number: 3 -Even number: 2 -Odd number: 1 -\end{lstlisting} - -\end{enumerate} diff --git a/full-speed-python.tex b/full-speed-python.tex deleted file mode 100644 index 7923f7d..0000000 --- a/full-speed-python.tex +++ /dev/null @@ -1,66 +0,0 @@ -\documentclass[12pt, a4paper, oneside]{book} - -% Fonts -\usepackage[]{opensans} -\usepackage[T1]{fontenc} -\usepackage[utf8]{inputenc} - -% Paragraphs -\setlength{\parindent}{0pt} -\setlength{\parskip}{6pt plus 2pt minus 1pt} - -% Margins -\usepackage[margin=1in]{geometry} - -% Images -\usepackage{graphicx} -\usepackage{float} - -% Source code -\usepackage{listings} -\usepackage{xcolor} - -% Source code formatting -\lstset{ - backgroundcolor=\color[rgb]{0.95,0.95,0.95}, - basicstyle=\footnotesize, - language=Python, - aboveskip=1em, - belowskip=1em, -} - -% Headers and footers -\pagestyle{plain} - -% Urls -\usepackage{hyperref} - -% Equations -\usepackage{amsmath} - - -\begin{document} - -\title{Full Speed Python} -\author{João Ventura} -\date{v0.3} - -\maketitle - -{ - \setcounter{tocdepth}{2} - \tableofcontents -} - -\include{chapters/introduction} -\include{chapters/installation} -\include{chapters/basic-datatypes} -\include{chapters/lists} -\include{chapters/functions} -\include{chapters/loops} -\include{chapters/dictionaries} -\include{chapters/classes} -\include{chapters/iterators} -\include{chapters/generators} - -\end{document} From e0b546c4be43dbeead3a8f183e4067b8ac516030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 18:14:07 +0100 Subject: [PATCH 31/59] Move latex preamble --- Makefile | 2 +- preamble.tex => tex/preamble.tex | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename preamble.tex => tex/preamble.tex (100%) diff --git a/Makefile b/Makefile index 309db20..82fe07f 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ epub: pdf: pandoc -o full-speed-python.pdf \ metadata.yaml \ - -H preamble.tex \ + -H latex/preamble.tex \ chapters/introduction.md \ chapters/installation.md \ chapters/basic-datatypes.md \ diff --git a/preamble.tex b/tex/preamble.tex similarity index 100% rename from preamble.tex rename to tex/preamble.tex From cb3bb5116adabd816edf4901d6441a32c5919943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 18:15:39 +0100 Subject: [PATCH 32/59] Fix reference to preamble --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 82fe07f..8afb79a 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ epub: pdf: pandoc -o full-speed-python.pdf \ metadata.yaml \ - -H latex/preamble.tex \ + -H tex/preamble.tex \ chapters/introduction.md \ chapters/installation.md \ chapters/basic-datatypes.md \ From 95e1de84c33696daa7617a29b907418044275292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 18:17:33 +0100 Subject: [PATCH 33/59] use default pandoc paragraph settings pdflatex --- tex/preamble.tex | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tex/preamble.tex b/tex/preamble.tex index 73c68e3..d94fc48 100644 --- a/tex/preamble.tex +++ b/tex/preamble.tex @@ -6,10 +6,6 @@ \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} -% Paragraphs -\setlength{\parindent}{0pt} -\setlength{\parskip}{6pt plus 2pt minus 1pt} - % Images \usepackage{graphicx} \usepackage{float} From 875910b19d8778fea155f7a103a0e3a96caf7d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 18:18:24 +0100 Subject: [PATCH 34/59] Remove latex source code listings --- tex/preamble.tex | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/tex/preamble.tex b/tex/preamble.tex index d94fc48..11763dc 100644 --- a/tex/preamble.tex +++ b/tex/preamble.tex @@ -15,19 +15,6 @@ \def\fps@figure{H} \makeatother -% Source code -\usepackage{listings} -\usepackage{xcolor} - -% Source code formatting -\lstset{ - backgroundcolor=\color[rgb]{0.95,0.95,0.95}, - basicstyle=\footnotesize, - language=Python, - aboveskip=1em, - belowskip=1em, -} - % Headers and footers \pagestyle{plain} From 979e8989d490ce833df638026b93519d773ad1a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 18:19:49 +0100 Subject: [PATCH 35/59] Remove amsmath from preamble --- tex/preamble.tex | 3 --- 1 file changed, 3 deletions(-) diff --git a/tex/preamble.tex b/tex/preamble.tex index 11763dc..c346de2 100644 --- a/tex/preamble.tex +++ b/tex/preamble.tex @@ -20,6 +20,3 @@ % Urls \usepackage{hyperref} - -% Equations -\usepackage{amsmath} From 36f859eca2519532f1964f9f7f80a31e35a49c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 28 Mar 2018 18:24:22 +0100 Subject: [PATCH 36/59] Update readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a14ab4..cb12139 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,6 @@ The source of this book is available on github (https://github.com/joaoventura/f ## Building -The pdf file is built with pdflatex, so you may need to download a latex distribution. The epub file is built with [pandoc](http://pandoc.org/). +Run `make pdf` or `make epub` to build the books. + +This project uses [pandoc](http://pandoc.org/) to build the books. The pdf file is built with pdflatex, so you may need to download a latex distribution. From e3b9bd624a041439fbb88a8239477bd53e17c13b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Thu, 29 Mar 2018 12:20:33 +0100 Subject: [PATCH 37/59] Simplify makefile --- Makefile | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index 8afb79a..445a32e 100644 --- a/Makefile +++ b/Makefile @@ -1,33 +1,22 @@ +chapters = \ + chapters/introduction.md \ + chapters/installation.md \ + chapters/basic-datatypes.md \ + chapters/lists.md \ + chapters/functions.md \ + chapters/loops.md \ + chapters/dictionaries.md \ + chapters/classes.md \ + chapters/iterators.md \ + chapters/generators.md \ + all: epub pdf epub: - pandoc -o full-speed-python.epub \ - metadata.yaml \ - chapters/introduction.md \ - chapters/installation.md \ - chapters/basic-datatypes.md \ - chapters/lists.md \ - chapters/functions.md \ - chapters/loops.md \ - chapters/dictionaries.md \ - chapters/classes.md \ - chapters/iterators.md \ - chapters/generators.md \ + pandoc -o full-speed-python.epub metadata.yaml $(chapters) pdf: - pandoc -o full-speed-python.pdf \ - metadata.yaml \ - -H tex/preamble.tex \ - chapters/introduction.md \ - chapters/installation.md \ - chapters/basic-datatypes.md \ - chapters/lists.md \ - chapters/functions.md \ - chapters/loops.md \ - chapters/dictionaries.md \ - chapters/classes.md \ - chapters/iterators.md \ - chapters/generators.md \ + pandoc -o full-speed-python.pdf metadata.yaml -H tex/preamble.tex $(chapters) clean: rm *.epub *.pdf From eef1a94857db575ca6c26b675d34a873e19e67e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Thu, 29 Mar 2018 12:21:25 +0100 Subject: [PATCH 38/59] Simplify gitignore --- .gitignore | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.gitignore b/.gitignore index 8a35989..16195f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,6 @@ # macOS .DS_Store -# Latex -*.aux -*.log -*.gz -*.out -*.toc - # Releases *.pdf *.epub From 82fadd634e8275111ec2b60d7f0dbd1402f0b036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Thu, 29 Mar 2018 12:23:31 +0100 Subject: [PATCH 39/59] Remove hyperref from latex preamble --- tex/preamble.tex | 3 --- 1 file changed, 3 deletions(-) diff --git a/tex/preamble.tex b/tex/preamble.tex index c346de2..9c18140 100644 --- a/tex/preamble.tex +++ b/tex/preamble.tex @@ -17,6 +17,3 @@ % Headers and footers \pagestyle{plain} - -% Urls -\usepackage{hyperref} From 7b4f48c8e4594d56ceb0e749e48690e9fcf6196a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Thu, 29 Mar 2018 12:28:17 +0100 Subject: [PATCH 40/59] Add image captions --- chapters/installation.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/chapters/installation.md b/chapters/installation.md index 0dbdcf3..7d58003 100644 --- a/chapters/installation.md +++ b/chapters/installation.md @@ -8,27 +8,27 @@ In this chapter we will install and run the Python interpreter in your local com 2. Make sure that the "Install launcher for all users" and "Add Python to PATH" settings are selected and choose "Customize installation". - ![image](images/python_windows.jpg){width=62%} + ![Windows installation](images/python_windows.jpg){width=62%} 3. In the next screen "Optional Features", you can install everything, but it is essential to install "pip" and "pylauncher (for all users)". Pip is the Python package manager that allows you to install several Python packages and libraries. 4. In the Advanced Options, make sure that you select "Add Python to environment variables". Also, I suggest that you change the install location to something like C:\\Python36\\ as it will be easier for you to find the Python installation if something goes wrong. - ![image](images/python_windows2.jpg){width=62%} + ![Windows installation](images/python_windows2.jpg){width=62%} 5. Finally, allow Python to use more than 260 characters on the file system by selecting "Disable path length limit" and close the installation dialog. - ![image](images/python_windows3.jpg){width=62%} + ![Windows installation](images/python_windows3.jpg){width=62%} 6. Now, open the command line (cmd) and execute "python" or "python3". If everything was correctly installed, you should see the Python REPL. The REPL (from Read, Evaluate, Print and Loop) is a environment that you can use to program small snippets of Python code. Run *exit()* to leave the REPL. - ![image](images/python_windows4.jpg){width=62%} + ![Python REPL](images/python_windows4.jpg){width=62%} ## Installing on macOS You can download the latest macOS binary releases from . Make sure you download the latest Python 3 release (3.6.4 at the time of writing). You can also use Homebrew, a package manager for macOS (). To install the latest Python 3 release with Homebrew, just do "`brew install python3`" on your terminal. Another option is to use the MacPorts package manager () and command "`port install python36`". -![image](images/python_macos.png){width=62%} +![Python REPL](images/python_macos.png){width=62%} Finally, open the terminal, execute `python3` and you should see the Python REPL as above. Press Ctrl+D or write `exit()` to leave the REPL. @@ -38,4 +38,4 @@ To install Python on Linux, you can download the latest Python 3 source releases Finally, open the terminal, execute `python3` and you should see the Python REPL as in the following image. Press Ctrl+D or write `exit()` to leave the REPL. -![image](images/python_linux.png){width=62%} +![Python REPL](images/python_linux.png){width=62%} From e06013267b78c73b6ee9a37e45989b3122c040d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Thu, 29 Mar 2018 12:58:42 +0100 Subject: [PATCH 41/59] Change code highlight style --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 445a32e..8c9de87 100644 --- a/Makefile +++ b/Makefile @@ -10,13 +10,15 @@ chapters = \ chapters/iterators.md \ chapters/generators.md \ +options = --highlight-style tango + all: epub pdf epub: - pandoc -o full-speed-python.epub metadata.yaml $(chapters) + pandoc -o full-speed-python.epub metadata.yaml $(options) $(chapters) pdf: - pandoc -o full-speed-python.pdf metadata.yaml -H tex/preamble.tex $(chapters) + pandoc -o full-speed-python.pdf metadata.yaml -H tex/preamble.tex $(options) $(chapters) clean: rm *.epub *.pdf From 3f644cd2814c8e29ae733bd1719778d2635bd257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Thu, 29 Mar 2018 13:05:06 +0100 Subject: [PATCH 42/59] Simplify makefile --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 8c9de87..806f9ee 100644 --- a/Makefile +++ b/Makefile @@ -10,15 +10,15 @@ chapters = \ chapters/iterators.md \ chapters/generators.md \ -options = --highlight-style tango +options = metadata.yaml --highlight-style tango all: epub pdf epub: - pandoc -o full-speed-python.epub metadata.yaml $(options) $(chapters) + pandoc -o full-speed-python.epub $(options) $(chapters) pdf: - pandoc -o full-speed-python.pdf metadata.yaml -H tex/preamble.tex $(options) $(chapters) + pandoc -o full-speed-python.pdf -H tex/preamble.tex $(options) $(chapters) clean: rm *.epub *.pdf From 3b26546dafd07d0491774e9287ab1edd8a70a02a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Thu, 29 Mar 2018 13:07:19 +0100 Subject: [PATCH 43/59] New version --- metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata.yaml b/metadata.yaml index fb28b8d..23c0605 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -1,6 +1,6 @@ --- title: Full Speed Python -subtitle: v0.4 +subtitle: v0.4.1 author: João Ventura language: en-US From 256c687f43ab5261c0faec947b75fcfc45e1fa97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Thu, 29 Mar 2018 19:40:48 +0100 Subject: [PATCH 44/59] New coroutines chapter --- Makefile | 1 + chapters/coroutines.md | 144 ++++++++++++++++++++++++++++++++ diagrams/consumers_pipeline.txt | 13 +++ diagrams/coroutine_pipeline.txt | 9 ++ diagrams/instructions.txt | 3 + images/consumers_pipeline.png | Bin 0 -> 21561 bytes images/coroutine_pipeline.png | Bin 0 -> 7704 bytes 7 files changed, 170 insertions(+) create mode 100644 chapters/coroutines.md create mode 100644 diagrams/consumers_pipeline.txt create mode 100644 diagrams/coroutine_pipeline.txt create mode 100644 diagrams/instructions.txt create mode 100644 images/consumers_pipeline.png create mode 100644 images/coroutine_pipeline.png diff --git a/Makefile b/Makefile index 806f9ee..5a5aea7 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ chapters = \ chapters/classes.md \ chapters/iterators.md \ chapters/generators.md \ + chapters/coroutines.md \ options = metadata.yaml --highlight-style tango diff --git a/chapters/coroutines.md b/chapters/coroutines.md new file mode 100644 index 0000000..e7382ad --- /dev/null +++ b/chapters/coroutines.md @@ -0,0 +1,144 @@ +# Coroutines + +Python coroutines are similar to generators but instead of producing data, coroutines are mostly used as data consumers. In other words, coroutines are functions that are resumed everytime a value is sent using the `send` method. + +The trick with coroutines is the use of the `yield` keyword on the right side of an assignment expression. Here's an example of a coroutine that just prints the values that are sent to it: + +```Python +def coroutine(): + print('My coroutine') + while True: + val = yield + print('Got', val) + +>>> co = coroutine() +>>> next(co) +My coroutine +>>> co.send(1) +Got 1 +>>> co.send(2) +Got 2 +>>> co.send(3) +Got 3 +``` + +The initial call to `next` is required to move the coroutine forward. You can see that it executes the print statement. Eventually, the function reaches the `yield` expression where it will wait to be resumed. Then, everytime a value is sent (with `send`), the coroutine function resumes from the `yield`, copies the value to **val** and prints it. + +Coroutines can be closed with the `close()` method. + +```Python +>>> co.close() +>>> co.send(4) +Traceback (most recent call last): + File "", line 1, in +StopIteration +``` + +## Exercises with coroutines + +1. Create a coroutine named "square" that prints the square of any sent value. + +2. Implement the "minimize" coroutine that keeps and prints the minimum value that is sent to the function. + +## Pipelines + +Coroutines can be used to implement data pipelines where one coroutine will send data to the next coroutine in the pipeline. Coroutines push data into the pipeline using the `send()` method. + +![](images/coroutine_pipeline.png) + +Here's an example of a small pipeline where the values sent to the producer coroutine are squared and sent to the consumer coroutine for printing: + +```Python +def producer(consumer): + print("Producer ready") + while True: + val = yield + consumer.send(val * val) + +def consumer(): + print("Consumer ready") + while True: + val = yield + print('Consumer got', val) +``` + +As above, coroutines must be "primed" with `next` before any value can be sent. + +```Python +>>> cons = consumer() +>>> prod = producer(cons) +>>> next(prod) +Producer ready +>>> next(cons) +Consumer ready + +>>> prod.send(1) +Consumer got 1 +>>> prod.send(2) +Consumer got 4 +>>> prod.send(3) +Consumer got 9 +``` + +Also, with coroutines, data can be sent to multiple destinations.The following example implements two consumers where the first only prints numbers in 0..10 and the second only print numbers in 10..20: + +```Python +def producer(consumers): + print("Producer ready") + try: + while True: + val = yield + for consumer in consumers: + consumer.send(val * val) + except GeneratorExit: + for consumer in consumers: + consumer.close() + +def consumer(name, low, high): + print("%s ready" % name) + try: + while True: + val = yield + if low < val < high: + print('%s got' % name, val) + except GeneratorExit: + print("%s closed" % name) +``` + +As before, coroutines must be "primed" before any value can be sent. + +```Python +>>> con1 = consumer('Consumer 1', 00, 10) +>>> con2 = consumer('Consumer 2', 10, 20) +>>> prod = producer([con1, con2]) + +>>> next(prod) +Producer ready +>>> next(con1) +Consumer 1 ready +>>> next(con2) +Consumer 2 ready + +>>> prod.send(1) +Consumer 1 got 1 +>>> prod.send(2) +Consumer 1 got 4 +>>> prod.send(3) +Consumer 1 got 9 +>>> prod.send(4) +Consumer 2 got 16 + +>>> prod.close() +Consumer 1 closed +Consumer 2 closed +``` + +The data is sent to all consumers but only the second executes the print statement. Notice the use of the `GeneratorExit` exception. Sometimes it can be useful to catch the exception and inform the downstream coroutines that the pipeline is no longer useful. + +![](images/consumers_pipeline.png) + +## Exercises with coroutine pipelines + +1. Implement a producer-consumer pipeline where the values squared by the producer are sent to two consumers. One should store and print the minimum value sent so far and the other the maximum value. + +2. Implement a producer-consumer pipeline where the values squared by the producer are dispatched to two consumers, one at a time. The first value should be sent to consumer 1, the second value to consumer 2, third value to consumer 1 again, and so on. Closing the producer should force the consumers to print a list with the numbers that each one obtained. diff --git a/diagrams/consumers_pipeline.txt b/diagrams/consumers_pipeline.txt new file mode 100644 index 0000000..95f9cd3 --- /dev/null +++ b/diagrams/consumers_pipeline.txt @@ -0,0 +1,13 @@ + +-------------+ + send() | | + +---->+ CONSUMER #1 | + | | | ++----------+ +----------+ | +-------------+ +| | send() | +--+ +| SOURCE +------->+ PRODUCER | +| | | +--+ ++----------+ +----------+ | +-------------+ + | | | + +---->+ CONSUMER #2 | + send() | | + +-------------+ diff --git a/diagrams/coroutine_pipeline.txt b/diagrams/coroutine_pipeline.txt new file mode 100644 index 0000000..b478032 --- /dev/null +++ b/diagrams/coroutine_pipeline.txt @@ -0,0 +1,9 @@ ++----------+ +-----------+ +-----------+ +| | send() | | send() | | +| SOURCE +------->+ COROUTINE +------->+ COROUTINE | +| | | | | | ++----------+ +-----------+ +-----------+ + + + + diff --git a/diagrams/instructions.txt b/diagrams/instructions.txt new file mode 100644 index 0000000..6ec9f8d --- /dev/null +++ b/diagrams/instructions.txt @@ -0,0 +1,3 @@ +1. Draw diagrams with http://asciiflow.com/ +2. Convert to png with http://ditaa.sourceforge.net/ +3. java -jar ditaa0_9.jar XXX.txt --scale 2 \ No newline at end of file diff --git a/images/consumers_pipeline.png b/images/consumers_pipeline.png new file mode 100644 index 0000000000000000000000000000000000000000..ecfeaa4fd4e5a784d5ad2e58b905d5584060d285 GIT binary patch literal 21561 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 literal 0 HcmV?d00001 diff --git a/images/coroutine_pipeline.png b/images/coroutine_pipeline.png new file mode 100644 index 0000000000000000000000000000000000000000..cff6b6356c679ad040eb4e663bc5b90b84790ac8 GIT binary patch literal 7704 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 Date: Thu, 29 Mar 2018 21:17:33 +0100 Subject: [PATCH 45/59] Bump version --- metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata.yaml b/metadata.yaml index 23c0605..35aa709 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -1,6 +1,6 @@ --- title: Full Speed Python -subtitle: v0.4.1 +subtitle: v0.4.2 author: João Ventura language: en-US From f5a2337c9d841e77704750cc1dce4204a0712daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Sun, 1 Apr 2018 00:18:17 +0100 Subject: [PATCH 46/59] Asyncio chapter --- Makefile | 1 + chapters/async.md | 89 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 chapters/async.md diff --git a/Makefile b/Makefile index 5a5aea7..6b36460 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ chapters = \ chapters/iterators.md \ chapters/generators.md \ chapters/coroutines.md \ + chapters/async.md \ options = metadata.yaml --highlight-style tango diff --git a/chapters/async.md b/chapters/async.md new file mode 100644 index 0000000..9e29f9d --- /dev/null +++ b/chapters/async.md @@ -0,0 +1,89 @@ +# Asynchronous programming + +So far we have been doing *synchronous programming*. Synchronous program execution is quite simple: a program starts at the first line, then each line is executed until the program reaches the end. Each time a function is called, the program waits for the function to return before continuing to the next line. + +In asynchronous programming, the execution of a function is usually non-blocking. In other words, each time you call a function it returns immediately. However, that function does not necessarily gets executed right way. Instead, there is usually a mechanism (called the "scheduler") which is responsible for the future execution of the function. + +The problem with asynchronous programming is that a program may end before any asynchronous function starts. A common solution for this is for asynchronous functions to return "futures" or "promises". These are objects that represent the state of execution of an async function. Finally, asynchronous programming frameworks typically have mechanisms to block or wait for those async functions to end based on those "future" objects. + +Since Python 3.6, the "asyncio" module combined with the *async* and *await* keyword allows us to implement what is called *co-operative multitasking programs*. In this type of programming, a coroutine function voluntarily yields control to another coroutine function when idle or when waiting for some input. + +Consider the following asynchronous function that squares a number and sleeps for one second before returning. Asynchronous functions are declared with **async def**. Ignore the **await** keyword for now: + +```Python +import asyncio + +async def square(x): + print('Square', x) + await asyncio.sleep(1) + print('End square', x) + return x * x + +# Create event loop +loop = asyncio.get_event_loop() + +# Run async function and wait for completion +results = loop.run_until_complete(square(1)) +print(results) + +# Close the loop +loop.close() +``` + +The event loop () is, among other things, the Python mechanism that schedules the execution of asynchronous functions. We use the loop to run the function until completion. This is a synchronizing mechanism that makes sure the next print statement doesn't execute until we have some results. + +The previous example is not a good example of asynchronous programming because we don't need that much complexity to execute only one function. However, imagine that you would need to execute the `square(x)` function three times, like this: + +```python +square(1) +square(2) +square(3) +``` + +Since the `square()` function has a sleep function inside, the total execution time of this program would be 3 seconds. However, given that the computer is going to be idle for a full second each time the function is executed, why can't we start the next call while the previous is sleeping? Here's how we do it: + +```Python +# Group tasks in list +tasks = [ + square(1), + square(2), + square(3) +] + +# Run async function and wait for completion +results = loop.run_until_complete(asyncio.gather(*tasks)) +print(results) +``` + +Basically, we add all calls to a list and use ``asyncio.gather(*tasks)`` to inform the loop to wait for all tasks to finish. Since the coroutines will start at almost the same time, the program will run for only 1 second. Asyncio **gather()** won't necessarily run the coroutines by order although it will return an ordered list of results. + +```Python +$ python3 python_async.py +Square 2 +Square 1 +Square 3 +End square 2 +End square 1 +End square 3 +[1, 4, 9] +``` + +Finally, async coroutine functions can **call other async coroutine functions** using the **await** keyword: + +```Python +async def compute_square(x): + await asyncio.sleep(1) + return x * x + +async def square(x): + print('Square', x) + res = await compute_square(x) + print('End square', x) + return res +``` + +## Exercises with asyncio + +1. Implement an asynchronous coroutine function to add two variables and sleep for the duration of the sum. Use the asyncio loop to call the function with two numbers. + +2. Change the previous program to schedule the execution of two calls to the sum function. From 9fcc99442a3b88825110488ce50cb38aacc66f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Sun, 1 Apr 2018 00:46:58 +0100 Subject: [PATCH 47/59] Include asyncio.as_completed() example --- chapters/async.md | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/chapters/async.md b/chapters/async.md index 9e29f9d..60d738a 100644 --- a/chapters/async.md +++ b/chapters/async.md @@ -43,19 +43,16 @@ square(3) Since the `square()` function has a sleep function inside, the total execution time of this program would be 3 seconds. However, given that the computer is going to be idle for a full second each time the function is executed, why can't we start the next call while the previous is sleeping? Here's how we do it: ```Python -# Group tasks in list -tasks = [ +# Run async function and wait for completion +results = loop.run_until_complete(asyncio.gather( square(1), square(2), square(3) -] - -# Run async function and wait for completion -results = loop.run_until_complete(asyncio.gather(*tasks)) +)) print(results) ``` -Basically, we add all calls to a list and use ``asyncio.gather(*tasks)`` to inform the loop to wait for all tasks to finish. Since the coroutines will start at almost the same time, the program will run for only 1 second. Asyncio **gather()** won't necessarily run the coroutines by order although it will return an ordered list of results. +Basically, we use ``asyncio.gather(*tasks)`` to inform the loop to wait for all tasks to finish. Since the coroutines will start at almost the same time, the program will run for only 1 second. Asyncio **gather()** won't necessarily run the coroutines by order although it will return an ordered list of results. ```Python $ python3 python_async.py @@ -68,7 +65,38 @@ End square 3 [1, 4, 9] ``` -Finally, async coroutine functions can **call other async coroutine functions** using the **await** keyword: +Sometimes results may be needed as soon as they are available. For that we can use a second coroutine that deals with each result using ``asyncio.as_completed()``: + +```Python +(...) + +async def when_done(tasks): + for res in asyncio.as_completed(tasks): + print('Result:', await res) + +loop = asyncio.get_event_loop() +loop.run_until_complete(when_done([ + square(1), + square(2), + square(3) +])) +``` + +This will print something like: + +```Python +Square 2 +Square 3 +Square 1 +End square 3 +Result: 9 +End square 1 +Result: 1 +End square 2 +Result: 4 +``` + +Finally, async coroutines can call **other async coroutine functions** with the **await** keyword: ```Python async def compute_square(x): From e043e174ce73810adca278aa33d4f15176089f4f Mon Sep 17 00:00:00 2001 From: Maarten den Braber Date: Wed, 4 Apr 2018 07:31:44 +0200 Subject: [PATCH 48/59] Module -> modulo --- chapters/basic-datatypes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/basic-datatypes.md b/chapters/basic-datatypes.md index 6fa5293..61a69d9 100644 --- a/chapters/basic-datatypes.md +++ b/chapters/basic-datatypes.md @@ -61,7 +61,7 @@ However, multiplication works as repetition: 3. The volume of a sphere is given by (4/3 * pi * r^3). Calculate the volume of a sphere of radius 5. Suggestion: create a variable named "pi" with the value of 3.1415. -4. Use the module operator (%) to check which of the following numbers is even or odd: (1, 5, 20, 60/7). +4. Use the modulo operator (%) to check which of the following numbers is even or odd: (1, 5, 20, 60/7). Suggestion: the remainder of \(x/2\) is always zero when \(x\) is even. From 205565c8ae35b539aa32530e61776ed9d5d1ebe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Ventura?= Date: Wed, 20 Jun 2018 20:17:56 +0100 Subject: [PATCH 49/59] New version 0.4.3 --- metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata.yaml b/metadata.yaml index 35aa709..f9c812f 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -1,6 +1,6 @@ --- title: Full Speed Python -subtitle: v0.4.2 +subtitle: v0.4.3 author: João Ventura language: en-US From df6b0560734b907f76d415c64e54f569e9bc6bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ventura?= Date: Thu, 6 Sep 2018 18:15:00 +0100 Subject: [PATCH 50/59] Fix typo in fibonnaci sequence exercise --- chapters/functions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chapters/functions.md b/chapters/functions.md index ec14de3..cf1103b 100644 --- a/chapters/functions.md +++ b/chapters/functions.md @@ -104,8 +104,8 @@ The trick with recursive functions is that there must be a "base" case where the \begin{equation} fib(n)=\begin{cases} - 0, & \text{if $x=0$}.\\ - 1, & \text{if $x=1$}.\\ + 0, & \text{if $n=0$}.\\ + 1, & \text{if $n=1$}.\\ fib(n-1) + fib(n-2), & \text{otherwise}. \end{cases} \end{equation} From bc4d68ebdd2cf7131e38b3626cb6ab667c32b1c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ventura?= Date: Thu, 6 Sep 2018 18:22:48 +0100 Subject: [PATCH 51/59] Make explicit the rectangle coordinates --- chapters/classes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chapters/classes.md b/chapters/classes.md index 4cd7233..2cffc7b 100644 --- a/chapters/classes.md +++ b/chapters/classes.md @@ -34,9 +34,9 @@ Hello, my name is Anna! Use the Python documentation on classes at to solve the following exercises. -1. Implement a class named "Rectangle" to store the coordinates of a rectangle given by (x1, y1) and (x2, y2). +1. Implement a class named "Rectangle" to store the coordinates of a rectangle given the top-left corner (x1, y1) and the bottom-right corner (x2, y2). -2. Implement the class constructor with the parameters (x1, y1, x2, y2) and store them in the class instances using the "self" keyword. +2. Implement the class constructor with the parameters (x1, y1, x2, y2) and store them in the class instance using the "self" keyword. 3. Implement the "width()" and "height()" methods which return, respectively, the width and height of a rectangle. Create two objects, instances of "Rectangle" to test the calculations. From 65b41816a8daa72bb3722adc2d142197c54df971 Mon Sep 17 00:00:00 2001 From: Robert Nix Date: Wed, 12 Sep 2018 09:13:49 -0500 Subject: [PATCH 52/59] Change in other others to in other words --- chapters/generators.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/generators.md b/chapters/generators.md index 62ed3a8..da266c3 100644 --- a/chapters/generators.md +++ b/chapters/generators.md @@ -1,6 +1,6 @@ # Generators -If you read the previous chapter, you know that iterators are objects that are regularly used with "for" loops. In other others, iterators are objects that implement the iteration protocol. A Python generator is a convenient way to implement an iterator. Instead of a class, a generator is a function which returns a value each time the "yield" keyword is used. Here’s an example of a generator to count the values between two numbers: +If you read the previous chapter, you know that iterators are objects that are regularly used with "for" loops. In other words, iterators are objects that implement the iteration protocol. A Python generator is a convenient way to implement an iterator. Instead of a class, a generator is a function which returns a value each time the "yield" keyword is used. Here’s an example of a generator to count the values between two numbers: ```Python def myrange(a, b): From 88eb8ec3f6b3e8236289ecfe5c19baf746eb50d4 Mon Sep 17 00:00:00 2001 From: Ralph Rooding Date: Mon, 4 Mar 2019 20:48:48 +0100 Subject: [PATCH 53/59] Fixed typo in Lists chapter --- chapters/lists.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/lists.md b/chapters/lists.md index 397088b..11fd299 100644 --- a/chapters/lists.md +++ b/chapters/lists.md @@ -66,7 +66,7 @@ Sometimes you may want to filter the elements by a given condition. The "if" key [0, 2, 4, 6, 8] ``` -The exemple above returns all even values in range 0..10. More about list comprehensions can be found at . +The example above returns all even values in range 0..10. More about list comprehensions can be found at . ## Exercises with list comprehensions From 819f77863e49d57b18fd06e1eced6d06020e9f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ventura?= Date: Fri, 18 Oct 2019 11:57:00 +0100 Subject: [PATCH 54/59] Update Makefile Force the use of numbers on chapters ans sections --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6b36460..7c023c0 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ chapters = \ chapters/coroutines.md \ chapters/async.md \ -options = metadata.yaml --highlight-style tango +options = metadata.yaml --highlight-style tango --number-sections all: epub pdf From 56274d76226ea72101402df4510e38d5bb7be4d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ventura?= Date: Fri, 18 Oct 2019 12:05:17 +0100 Subject: [PATCH 55/59] Update metadata.yaml Use correct key for setting the language --- metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata.yaml b/metadata.yaml index f9c812f..dbbb6ec 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -2,7 +2,7 @@ title: Full Speed Python subtitle: v0.4.3 author: João Ventura -language: en-US +lang: en-US # Variables for Latex documentclass: book From ef09d5ab7eb381db0d6ae9f2098e41b9807ea2b5 Mon Sep 17 00:00:00 2001 From: Dieter Vansteenwegen Date: Wed, 23 Feb 2022 10:52:21 +0100 Subject: [PATCH 56/59] Corrected formula to match results --- chapters/iterators.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/iterators.md b/chapters/iterators.md index 5344ddb..49facb4 100644 --- a/chapters/iterators.md +++ b/chapters/iterators.md @@ -4,7 +4,7 @@ As we saw previously, in Python we use the "for" loop to iterate over the conten ```Python >>> for value in [0, 1, 2, 3, 4, 5]: -... print(value) +... print(value*value) ... 0 1 From 2f45beff33794128b20ab1c5e50744ed488d9abf Mon Sep 17 00:00:00 2001 From: Jozef Sevcik Date: Mon, 16 Jan 2023 13:34:57 +0100 Subject: [PATCH 57/59] Fix typo in Modules and functions chapter --- chapters/functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/functions.md b/chapters/functions.md index cf1103b..f518191 100644 --- a/chapters/functions.md +++ b/chapters/functions.md @@ -26,7 +26,7 @@ World Make sure that you insert a tab before both print expressions in the previous function. Tabs and spaces in Python are relevant and define that a block of code is somewhat dependent on a previous instruction. For instance, the print expressions are "inside" the "do\_hello" function therefore must have a tab. -Functions can also receive parameters a return values (using the "return" keyword): +Functions can also receive parameters and return values (using the "return" keyword): ```Python >>> def add_one(val): From 34640fc3c86024a3e3ca901c4c4561921b99faf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ventura?= Date: Thu, 9 Mar 2023 12:45:56 +0000 Subject: [PATCH 58/59] Add link to gumroad --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cb12139..c18eb5b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Full Speed Python -Pdf and epub files can be downloaded from: https://github.com/joaoventura/full-speed-python/releases/ +Pdf and epub files can be downloaded from: https://jventura.gumroad.com/l/fullspeedpython. The ebooks are free (as in 0.00€), but if you want to support my work and allow me to improve it, you can set any other price. This book aims to teach the Python programming language using a practical approach. Its method is quite simple: after a short introduction to each topic, the reader is invited to learn more by solving the proposed exercises. From 35a854208b2ed43f00e025585c8c4d87322ccda0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ventura?= Date: Thu, 9 Mar 2023 12:49:57 +0000 Subject: [PATCH 59/59] Update readme --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c18eb5b..73f4009 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Full Speed Python -Pdf and epub files can be downloaded from: https://jventura.gumroad.com/l/fullspeedpython. The ebooks are free (as in 0.00€), but if you want to support my work and allow me to improve it, you can set any other price. +### About This book aims to teach the Python programming language using a practical approach. Its method is quite simple: after a short introduction to each topic, the reader is invited to learn more by solving the proposed exercises. @@ -8,6 +8,9 @@ These exercises have been used extensively in my web development and distributed The source of this book is available on github (https://github.com/joaoventura/full-speed-python). I welcome any pull requests to correct misspellings, suggest new exercises or to provide clarification of the current content. +### How to get the ebook? + +Pdf and epub files can be downloaded from: https://jventura.gumroad.com/l/fullspeedpython. The ebooks are free (as in free beer!), but if you want to support my work and allow me to improve it, you can set any other price. ## Building