From 50d1dd3feb6ebaa8ee62aaf1d8d1827ebab85f82 Mon Sep 17 00:00:00 2001 From: Robin Engler Date: Thu, 7 Mar 2024 17:53:59 +0100 Subject: [PATCH] notebook 1: add small section on methods. Move tuples after lists --- notebooks/01_python_basics.ipynb | 397 +++++++++++++++++++++---------- 1 file changed, 273 insertions(+), 124 deletions(-) diff --git a/notebooks/01_python_basics.ipynb b/notebooks/01_python_basics.ipynb index 4286034..88731bf 100644 --- a/notebooks/01_python_basics.ipynb +++ b/notebooks/01_python_basics.ipynb @@ -386,6 +386,67 @@ "**Don't hesitate to use the `help` function on any object (e.g. functions) to understand how they work.**" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "\n", + "[Back to ToC](#toc)\n", + "\n", + "### Methods\n", + "\n", + "**Methods** are very similar to functions, except that they **are associated to a specific object type**. \n", + "Since methods are associated to a specific object type, the syntax used to call them is the following:\n", + "\n", + "* `object.method()` - syntax to call a **method of an object**.\n", + "\n", + "\n", + "
\n", + "\n", + "**Example:** calling the `.upper()` method of a string." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test_string = \"hello world!\"\n", + "upper_case_string = test_string.upper()\n", + "print(upper_case_string)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "\n", + "**Methods are a very important part of python**, and provide tons of functionalities to objects. \n", + "Before you start writing your own code to manipulate an object, **always check** if the object\n", + "already has a method that does exactly (or nearly) what you want.\n", + "This will save you a lot of time and grief.\n", + "\n", + "\n", + "In the help, **methods can be idientified** by the fact that their first argument is the special keyword **`self`**.\n", + "\n", + "Example of `help(str.upper)`:\n", + "\n", + "```py\n", + "upper(self, /)\n", + " Return a copy of the string converted to uppercase.\n", + "```\n", + "\n", + "
\n", + "\n", + "> Note: the `/` symbol found in some method signatures indicates that all arguments\n", + " present before the `/` are positional arguments, even if they have a default value.\n", + " They have to be passed in the correct order, and cannot be passed with their argument\n", + " name, i.e. `argument_name=value`." + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -1162,16 +1223,25 @@ "\n", "## Lists and tuples \n", "\n", - "Lists and tuples are **sequence type** objects that can contain any type of elements (other objects).\n", + "Lists are **sequence type** objects that can contain any type of element (other objects).\n", "* **Lists** are declared by surrounding a comma separated list of objects with **`[]`**.\n", - "* **Tuples** are declared similarly, but using **`()`**." + "\n", + "
\n", + "\n", + "#### Creating a list" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ - "#### Create a list" + "# Create a new list.\n", + "my_list = [\"item 0\", \"item 1\", \"item 2\"]\n", + "\n", + "print(\"The content of my_list is:\", my_list)\n", + "print(\"length of my list is:\", len(my_list))" ] }, { @@ -1180,12 +1250,6 @@ "metadata": {}, "outputs": [], "source": [ - "# Create a new list.\n", - "my_list = [\"item 0\", \"item 1\", \"item 2\"]\n", - "\n", - "print(\"The content of my_list is:\", my_list)\n", - "print(\"length of my list is:\", len(my_list))\n", - "\n", "# Create a new list.\n", "another_list = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]\n", "\n", @@ -1198,7 +1262,7 @@ "metadata": {}, "source": [ "* List items can be of **heterogenous type**.\n", - "* List items can be of any type: therefore it's possible to nest lists within each other." + "* List items can be of any type: therefore it's possible to nest lists within other lists." ] }, { @@ -1217,14 +1281,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Create a tuple\n", - " * **Important:** if a tuple contains a single element, then the last (and only) element of the tuple must be\n", - " followed by a comma.\n", - " * If the tuple contains multiple elements, then this is not necessary (but possible).\n", - " ```py\n", - " a_tuple = (value, )` # Correct syntax.\n", - " a_tuple = (value) # This will NOT create a tuple, but a regular value.\n", - " ```" + "
\n", + "\n", + "#### Creating an empty list" ] }, { @@ -1233,24 +1292,20 @@ "metadata": {}, "outputs": [], "source": [ - "tuple_1 = (\"spam\", )\n", - "\n", - "print(\"Content of variable:\", tuple_1)\n", - "print(\"Length of tuple is :\", len(tuple_1))\n", - "print(\"type of variable :\", type(tuple_1))" + "list_1 = []\n", + "list_1 = list()\n", + "print(\"Content:\", list_1, \" Type:\", type(list_1), \" Length:\", len(list_1))" ] }, { "cell_type": "markdown", - "metadata": { - "vscode": { - "languageId": "python" - } - }, + "metadata": {}, "source": [ "
\n", "\n", - "**Warning:** the following does not create a tuple, but a variable of type string!" + "#### Creating lists from iterables (e.g. sequences such as lists, tuples, or a range)\n", + "\n", + "* Objects that are *iterables* can be converted to lists using the `list()` function." ] }, { @@ -1259,32 +1314,42 @@ "metadata": {}, "outputs": [], "source": [ - "tuple_1 = (\"spam\")\n", - "print(\"Content of variable:\", tuple_1)\n", - "print(\"Length of variable :\", len(tuple_1))\n", - "print(\"type of variable :\", type(tuple_1))" + "# Creating a list from a \"range\" type object.\n", + "list_1 = list(range(21))\n", + "print(list_1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "
\n", - "\n", - "* Since tuples can contain any type of objects, they can also contain lists or other tuples (or lists):" + "> What are **`range`** objects? \n", + "> `range` objects are sequences of **integer numbers**, e.g. `0, 1, 2, 3, 4, ...`.\n", + ">\n", + "> By default, a call to `range(x)` creates a sequence of integers from `0` to `x`, `x` excluded.\n", + ">\n", + "> **Examples**:\n", + "> * `range(10` -> `0, 1, 2, 3, 4, 5, 6, 7, 8, 9`\n", + "> * `range(3, 7)` -> `3, 4, 5, 6`" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "tuple_2 = ('a', 4.2, 5, [2, \"spam\"])\n", + "
\n", + "\n", + "[Back to ToC](#toc)\n", + "\n", + "### Accessing values: list slicing \n", + "\n", + "* Accessing an element (or a range of elements) in a list is done using the **`[]`** operator.\n", + "* The **`[]` operator** works in much the same way than with strings, and allows\n", + " **accessing individual objects** from a list, or **slicing** it.\n", + "\n", + "\"representation\n", "\n", - "print(\"The content of the tuple is:\", tuple_2)\n", - "print(\"The length of tuple is:\", len(tuple_2))\n", - "print(\"The last element of the tuple is:\", tuple_2[-1]) # The last element is a list!" + "* As with strings, remember that the end position index is **excluded** from the slicing." ] }, { @@ -1293,39 +1358,65 @@ "metadata": {}, "outputs": [], "source": [ - "# The second element of the list in last position of the tuple:\n", - "print(\"The 2nd element of the list in last position of the tuple is:\", tuple_2[-1][1])" + "my_list = [1, 2, \"spam\", \"eggs\", 5.2, [2, \"spam\"]]\n", + "\n", + "print(my_list)\n", + "print(my_list[0]) # Get the 1st item of the list.\n", + "print(my_list[2:]) # Get all elements from index 2 (i.e. the 3rd element) to the end of the list." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Creating empty lists and tuples" + "
\n", + "\n", + "* If we try to access an index that does not exist in the list, an **`IndexError`** is raised.\n", + "\n", + "```py\n", + " my_list = [1, 2, \"spam\"]\n", + " my_list[3]\n", + "\n", + " ---------------------------------------------------------------------------\n", + " IndexError Traceback (most recent call last)\n", + " Input In [26], in \n", + " 1 my_list = [1, 2, \"spam\"]\n", + " ----> 2 my_list[3]\n", + "\n", + " IndexError: list index out of range\n", + "```" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "list_1 = []\n", - "list_1 = list()\n", - "print(\"Content:\", list_1, \" Type:\", type(list_1), \" Length:\", len(list_1))\n", + "
\n", "\n", - "tuple_1 = ()\n", - "tuple_1 = tuple()\n", - "print(\"Content:\", tuple_1, \" Type:\", type(tuple_1), \" Length:\", len(tuple_1))" + "[Back to ToC](#toc)\n", + "\n", + "### Tuples\n", + "\n", + "Tuples are very similar to lists in that they also are a **sequence type** objects that can contain any type of element (other objects). \n", + "* **Tuples** are declared using the syntax **`(value1, value2, ...)`**.\n", + "* Values in **tuples** can be accessed and sliced in the same way as lists are.\n", + "* The main difference between lists and tuples is that **the values in a tuple cannot be changed**\n", + " once the tuple has been created. This means that we cannot add/remove values from a tuple, nor can\n", + " we modify a value inside it." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Creating lists and tuples from iterables (e.g. sequences such as lists/tuples, range)\n", - "\n", - "* Objects that are *iterables* can be converted to lists or tuples." + "#### Create a tuple\n", + " * **Important:** if a tuple contains a single element, then the last (and only) element of the tuple must be\n", + " followed by a comma.\n", + " * If the tuple contains multiple elements, then this is not necessary (but possible).\n", + " ```py\n", + " a_tuple = (value, )` # Correct syntax.\n", + " a_tuple = (value) # This will NOT create a tuple, but a regular value.\n", + " ```" ] }, { @@ -1334,49 +1425,48 @@ "metadata": {}, "outputs": [], "source": [ - "list_1 = list((1, 2, 3)) # Converting a tuple to a list.\n", - "tuple_1 = tuple([1, 2, 3]) # Converting a list to a tuple.\n", - "print(list_1)\n", - "print(tuple_1)\n", - "\n", - "# Creating a list/tuple from a \"range\" type object.\n", - "list_1 = list(range(21))\n", - "tuple_1 = tuple(range(21))\n", - "print(list_1)\n", + "# Create a tuple of 3 elements.\n", + "tuple_1 = (\"spam\", \"eggs\", \"coconuts\")\n", "print(tuple_1)" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ - "> What are **`range`** objects? \n", - "> `range` objects are sequences of **integer numbers**, e.g. `0, 1, 2, 3, 4, ...`.\n", - ">\n", - "> By default, a call to `range(x)` creates a sequence of integers from `0` to `x`, `x` excluded.\n", - ">\n", - "> **Examples**:\n", - "> * `range(10` -> `0, 1, 2, 3, 4, 5, 6, 7, 8, 9`\n", - "> * `range(3, 7)` -> `3, 4, 5, 6`" + "# Create a tuple of 1 element.\n", + "tuple_1 = (\"spam\", )\n", + "\n", + "print(\"Content of variable:\", tuple_1)\n", + "print(\"Length of tuple is :\", len(tuple_1))\n", + "print(\"type of variable :\", type(tuple_1))" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], + "source": [ + "# Create a tuple from a list.\n", + "list_1 = [\"a\", \"sequence\", \"of\", \"strings\"]\n", + "tuple_1 = tuple(list_1)\n", + "print(tuple_1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "vscode": { + "languageId": "python" + } + }, "source": [ "
\n", "\n", - "[Back to ToC](#toc)\n", - "\n", - "### Accessing values: list and tuple slicing \n", - "\n", - "* Accessing an element (or a range of elements) in a list or tuple is done using the **`[]`** operator.\n", - "* The **`[]` operator** works in much the same way than with strings, and allows\n", - " **accessing individual objects** from a list/tuple, or **slicing** it.\n", - "\n", - "\"representation\n", - "\n", - "* As with strings, remember that the end position index is **excluded** from the slicing." + "**Warning:** the following does not create a tuple, but a variable of type string!" ] }, { @@ -1385,12 +1475,10 @@ "metadata": {}, "outputs": [], "source": [ - "my_list = [1, 2, \"spam\", \"eggs\", 5.2, [2, \"spam\"]]\n", - "my_tuple = tuple(my_list)\n", - "\n", - "print(my_list)\n", - "print(my_tuple[0]) # Get the 1st item of the tuple.\n", - "print(my_list[2:]) # Get all elements from index 2 (i.e. the 3rd element) to the end of the list.\n" + "tuple_1 = (\"spam\")\n", + "print(\"Content of variable:\", tuple_1)\n", + "print(\"Length of variable :\", len(tuple_1))\n", + "print(\"type of variable :\", type(tuple_1))" ] }, { @@ -1399,21 +1487,21 @@ "source": [ "
\n", "\n", - "* If we try to access an index that does not exist in the list/tuple, an **`IndexError`** is raised.\n", - "\n", - "> If we try to access an index that does not exist in the list/tuple, an **`IndexError`** is raised.\n", - "```py\n", - " my_list = [1, 2, \"spam\"]\n", - " my_list[3]\n", - "\n", - " ---------------------------------------------------------------------------\n", - " IndexError Traceback (most recent call last)\n", - " Input In [26], in \n", - " 1 my_list = [1, 2, \"spam\"]\n", - " ----> 2 my_list[3]\n", - "\n", - " IndexError: list index out of range\n", - "```" + "#### Creating emtpy tuples\n", + "* Empty tuples can be created with `()` or `tuple()`.\n", + "* Note that because tuples cannot be changed after they are created, it is not possible to add elements\n", + " to an empty tuple." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tuple_1 = ()\n", + "tuple_1 = tuple()\n", + "print(\"Content:\", tuple_1, \" Type:\", type(tuple_1), \" Length:\", len(tuple_1))" ] }, { @@ -1422,12 +1510,10 @@ "source": [ "
\n", "\n", - "[Back to ToC](#toc)\n", - "\n", "### When to use `list` or `tuple`? Mutability - an important difference between lists and tuples \n", "\n", - "* A `tuple` is **immutable**: its length is fixed and its elements cannot be changed.\n", "* A `list` is **mutable**: it can be extended, reduced, and its elements can be changed.\n", + "* A `tuple` is **immutable**: its length is fixed and its elements cannot be changed.\n", "\n", "
\n", "\n", @@ -1844,16 +1930,6 @@ "print(\"list after insert:\", my_list)" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "> **Methods are a very important part of python**, and provide tons of functionalities to objects. \n", - "> Before you start writing your own code to manipulate an object, **always check** if the object\n", - "> already has a method that does exactly (or nearly) what you want.\n", - "> This will save you a lot of time and grief." - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -2062,6 +2138,79 @@ "outputs": [], "source": [] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + "
\n", + "\n", + "### Returning a value vs. in-place modification\n", + "\n", + "As you might have noticed, methods do sometimes return a value, and sometimes modify an object \"inplace\", meaning that the object on which the method is called is itself modified.\n", + "\n", + "**Example:** the `.upper()` method of a string object returns a value. It does not modify the original string." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "a_quote = \"You must cut down the mightiest tree in the forest with a herring!\"\n", + "return_value = a_quote.upper()\n", + "print(\"The return value is:\", return_value)\n", + "print(\"The original object:\", a_quote) # The original object has not been changed." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "\n", + "**Example:** The `.append()` method of a list **modifies the list inplace**, and returns the value `None`.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "more_quotes = [\n", + " \"What… is your quest?\",\n", + " \"To seek the Holy Grail\",\n", + "]\n", + "return_value = more_quotes.append(\"Well, how did you become king then?\")\n", + "\n", + "print(\"The return value is:\", return_value)\n", + "print(\"The original object:\", more_quotes)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "\n", + "When calling a method that modifies the object inplace and returns `None`, we generally do not store the return value in a variable. \n", + "Appending a value to a list would thus be written as:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "more_quotes.append(\"Well, how did you become king then?\")" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -2764,7 +2913,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.3" + "version": "3.10.12" } }, "nbformat": 4,