{ "cells": [ { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-e68e92ac1082dd04", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "# Data types\n", "\n", "```{admonition} Interactive page\n", ":class: warning, dropdown\n", "This is an interactive book page. Press the launch button at the top right side.\n", "```\n", "\n", "In Python, we can assign values to variables.\n", "Variables have a property that is called their **type**.\n", "In the previous chapter, you've seen a few lines of Python code in which we assigned a value (either integer or string) to a variable using the assignment operator `=` (see [previous chapter](../chapter3/python-characteristics.ipynb)), and Python automatically picked a variable type it thinks fits best.\n", "You can use `type()` function to check the data type - try it out for `a` and `b`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "a = 1\n", "b = \"Python is cool\"\n", "\n", "print(type(a))\n", "print(type(b))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{admonition} Function inside a function\n", ":class: note, dropdown\n", "In the code above, we've seen a line like this: `print(type(a))`.\n", "In Python, it's possible to \"engulf\" a function within another function; in this case, `type()` is within `print()`.\n", "Effectively, this means that we will \"print the type of `a`\".\n", "In other words, the function on the inside is the first one to have an effect on variable `a`.\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Built-in data types \n", "\n", "As you can imagine, there are many more data types in Python besides integer and string. Before we delve into some of these types in detail, here we offer a general overview.\n", "\n", "```{list-table} Python built-in data types.\n", ":header-rows: 1\n", ":name: data-types\n", "\n", "* - \n", " - Data type\n", " - Example\n", " - Usage\n", "* - Text type\n", " - `str`\n", " - `x = \"Hello world\"`\n", " - Textual data\n", "* - Numeric types\n", " - `int`\n", " - `x = -10`\n", " - Integer numbers; counting; indexing\n", "* - \n", " - `float`\n", " - `x = 2.5`\n", " - Rational numbers\n", "* - \n", " - `complex`\n", " - `x = 2 + 5j`\n", " - Irrational numbers\n", "* - Boolean type\n", " - `bool`\n", " - `x = True`\n", " - Represent truth values; indicate binary states; conditional statements\n", "* - Sequence types\n", " - `list`\n", " - `x = [\"math\", \"physics\", \"biology\"]`\n", " - Ordered, mutable collections of items\n", "* - \n", " - `tuple`\n", " - `x = (\"math\", \"physics\", \"biology\")`\n", " - Ordered, immutable collections of items\n", "* - \n", " - `range`\n", " - `x = range(5)`\n", " - Generating a sequence of numbers; in `for` loops\n", "* - Mapping type\n", " - `dict`\n", " - `x = {\"name\": \"Johan\", \"grade\": 9.5}`\n", " - Storing and retrieving data based on unique keys\n", "* - Set types\n", " - `set`\n", " - `x = {\"math\", \"physics\", \"biology\"}`\n", " - Unordered collections of unique items; removing duplicates\n", "* - \n", " - `frozenset`\n", " - `x = frozenset({\"math\", \"physics\", \"biology\"})`\n", " - Unordered collections of unique items that should be immutable\n", "* - None type\n", " - `NoneType`\n", " - `x = None`\n", " - Absence of a value or a null value\n", "```\n", "\n", "As you may have noticed, each data type has specific use cases. Depending on what your code is doing, you will **choose which types are appropriate** for your variables.\n", "We will next expolore some of these types in more detail; others will be discussed later. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Text type\n", "\n", "We've already encountered the \"string\" variable type `str`, which is used for **pieces of text**. To tell Python you want to make a string, you enclose the text of your string in either single forward quotes `'` or double forward quotes `\"`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "c = \"This is a string\"\n", "d = 'This is also a string'\n", "\n", "print(type(c))\n", "print(type(d))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also make **multiline** strings using three single quotes:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "multi = \\\n", "'''\n", "This string\n", "has \n", "multiple lines.\n", "'''\n", "\n", "print(multi)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that we used a **backslash**, which is a way to **split Python code across multiple lines**. \n", "\n", "Although it's not obvious, Python can also do \"operations\" on strings: the `+` mathematical operators we saw above also work with strings. \n", "\n", "```{exercise}\n", ":class: dropdown\n", "Discover what the `+` operator does to a string: print the output of the sum of two strings.\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "# your code here" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-6f2bfadc72282277", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "### Numeric types\n", "\n", "We've seen that variables with integer numbers get assigned the `int` type.\n", "If we assign a non-integer number to a variable, Python has to choose another type instead of `int`. \n", "For variable `f` in the code below, Python will select the type `float`, which corresponds to floating point numbers. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "f = 2.5\n", "print(type(f))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*In general, Python tries to choose a variable type that makes calculations the fastest and uses as little memory as possible.*\n", "\n", "If you assign a new value to a variable, it **can change the variable type**:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "f = 5\n", "print(type(f))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Observe what happens in the following case:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "f = 5\n", "print(type(f))\n", "\n", "f = f/2\n", "print(type(f))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What happened in this code?\n", "In the first line, we assigned the value of 5 to variable `f` using the assignment operator `=`.\n", "In the second line, `f/2` indicated division of the current value of `f` (which is 5) by number 2. \n", "The result of this multiplication is 2.5. \n", "Then we use assignment operator `=` to assign the value of 2.5 to variable `f`.\n", "In essence, the second line of the code updates variable `f` to be two times smaller than its previous value.\n", "\n", "In this example, because 5/2 = 2.5, Python decided to change the type of variable `f` from `int` to `float` after the assignment operation `f = f/2`. \n", "\n", "When you are using floating point numbers, you can also use **\"exponential\" notation** to specify very big or very small numbers: " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "f = 1.5e-8" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-9f4aa0b51687698a", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "The notation `1.5e-8` is a notation used in Python to indicate the number $1.5 \\times 10^{-8}$.\n", "\n", "A third type of mathematical variable type that you may use in nanobiology is a complex number. In Python, you can indicate a **complex number** by using `j`, which is the Python notation for the complex number $i$:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "d = 1+2j\n", "print(type(d))" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-212eb128ab19078d", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "The notation `j` is special, in particular because there is **no space** between the number preceding it (in this case `2`) and `j`. This is how Python knows that you are telling it to make a complex number (and not just referring to a variable named `j`). The number in front of the `j` can be any floating point number:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "1 + 0.5j" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-1fa7be3de8eb7f5a", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "### Boolean type\n", "\n", "\"Boolean\" type `bool` is another very useful type of variable. Boolean variables can have two values: `True` and `False`. You type them in directly as `True` and `False` with **no quotes**." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "g = False\n", "print(type(g))" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-12ff71b21d9d01e3", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "We will use Boolean types extensively later when we'll look at the [**flow control**](../chapter6/cond-loops.md), but a simple example using the `if` statement is given below.\n", "Don't panic if you don't understand the `if` statement yet, there will be another entire section dedicated to it. At this point, this is just an example of why Boolean variables exist." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "g = True\n", "\n", "if True:\n", " print(\"True is always true.\")\n", "\n", "if g:\n", " print(\"g is true!\")\n", " \n", "if not g:\n", " print(\"g is not true!\")" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-7f2acb9e44b581d8", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "You can try changing the value of `g` above to `False` and see what happens if you run the above code cell again.\n", "\n", "```{admonition} Numbers and True/False statements\n", ":class: tip\n", "Numbers (both `int` and `float`) can also be used in `True` / `False` statements. Python will interpret **any number that is not zero** as `True` and **any number that is zero** as `False`. \n", "```\n", "\n", "```{exercise}\n", ":class: dropdown\n", "Discover which numbers can be used as `True` and `False` in Python by changing the value of `g` above and re-running the code.\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Sequence types\n", "\n", "It often happens that you want to **store data that belong together** (a collection of items). There are several options to do this. Here we will focus on lists and tuples. [Later](../chapter7/numpy-intro.md) we will also see NumPy arrays, which are not a Python built-in type, but are extremely useful to scientists.\n", "\n", "Think of storing personal data, where we need to know first name, family name, address, and city, in a **list**:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "Person_1 = ['Jana', 'Bakker', 'Lorentzweg', 1, 'Delft']\n", "print(Person_1)\n", "\n", "# Person_1 type\n", "print(type(Person_1)) \n", "\n", "# Type for first and third element\n", "print(type(Person_1[0]), type(Person_1[3]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is interesting to see that `Person_1` is a list and that within the list other types exist.\n", "\n", "```{note}\n", "We can **access** elements in a list using square brackets `[ ]`.\n", "The **first item is referred to by 0** because Python starts to count from 0. \n", "Using a numerical index to access an elements from a list is called **indexing**.\n", "```\n", " \n", "If we make a mistake, we can replace an item in the list." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "Person_1 = ['Jana', 'Bakker', 'Lorentzweg', 1, 'Delft']\n", "Person_1[0] = 'Anna'\n", "print(Person_1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another way we can store data is by using a **tuple**. Note that the only difference in notation, compared to a list, is the use of **parentheses**." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "Person_2 = ('Johan', 'Vos', 'Mekelweg', 5, 'Delft')\n", "print(Person_2)\n", "print(type(Person_2), type(Person_2[0]), type(Person_2[3]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What is the difference between a list and a tuple? The most important difference is that **tuples are immutable**, i.e., you cannot change them as we could a list:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "Person_2 = ('Johan', 'Vos', 'Mekelweg', 5, 'Delft')\n", "Person_2[1] = 'Jansen'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{admonition} A peculiar case of a = b\n", ":class: note\n", "Let's look at a peculiar example in the code cell below. Go to the code cell and excecute it. What do you observe?\n", "\n", "In this example, something strange happens. We did not change `a`, did we? \n", "\n", "A \"funny\" thing happens with the command `b = a`. As we say that `b` and `a` are the same, rather than creating a new spot in the memory where the information is stored, `b` and `a` obtain the same memory address. If we call upon `a`, Python searches its memory, and obtains the data stored at that unique ID. We can see this using `id()` function (try it out in the code cell above). \n", "This is important to know because if we say `b = ` and we change the value of `b`, the value of `a` changes as well! \n", "Therefore, in this example, `b` is not a copy of `a` with a new location in the memory. Instead, `b` obtains the same location in the memory. \n", "\n", "This peculiarity holds true for **mutable objects** in Python, therefore:\n", "- **Mutable objects**: content can be changed after creation (e.g., list, dict, set).\n", "- **Immutable objects**: content cannot be changed (e.g., int, float, str, tuple).\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "# A peculiar case of a = b\n", "\n", "a = [2, 3, 4]\n", "b = a\n", "b[0] = -10\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also make tuples with only a single item stored. However, we must use a comma; otherwise, Python will not recognize it as a tuple." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "# Not a tuple\n", "n_a_t = (1)\n", "print(type(n_a_t))\n", "\n", "# A tuple\n", "a_t = (1,)\n", "print(type(a_t))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lists are mutable and are thus called **variables**. However, a tuple cannot be varied and is thus not a variable - it's called an **object**. Since it's immutable, a tuple requires less space. We can still make effective use of tuples (and lists):" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "a = [2,3,5]\n", "b = (2,3,5)\n", "print(a[0]*2)\n", "print(b[0]*2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "thebe-remove-input-init" ] }, "outputs": [], "source": [ "import micropip\n", "await micropip.install(\"jupyterquiz\")\n", "from jupyterquiz import display_quiz\n", "import json\n", "\n", "with open(\"questions4.json\", \"r\") as file:\n", " questions=json.load(file)\n", " \n", "display_quiz(questions, border_radius=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Mapping type\n", "\n", "The last type of data we'll take a closer look at now is the mapping type called **dictionary**.\n", "Python dictionaries store data in a **key:value pairs**, where **values can be of any type**, and each value is associated with a unique key. \n", "A value in a dictionary can then quickly be **accessed using the corresponding key name**.\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "d = {\n", " \"name\": \"hemoglobin\",\n", " \"organism\": \"human\",\n", " \"length\": 142\n", "}\n", "\n", "print(d)\n", "print(type(d))\n", "\n", "# Access the value associated with \"length\" key\n", "print(d[\"length\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we have dictionary items of string (\"hemoglobin\", \"human\") and integer (142) types. In principle, dictionary items can be of any type:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "d = {\n", " \"name\": \"hemoglobin\",\n", " \"organism\": \"human\",\n", " \"length\": 142,\n", " \"multimeric\": True,\n", " \"subunits\": [\"alpha\", \"beta\"]\n", "}\n", "\n", "print(d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We mentioned the requirement for the dictionary keys to be unique. Otherwise, how would Python know which dictionary item you're referring to? Let's see what happens if you introduce **duplicates** into a dictionary:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "d = {\n", " \"name\": \"hemoglobin\",\n", " \"organism\": \"human\",\n", " \"length\": 142,\n", " \"length\": 95\n", "}\n", "\n", "print(d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you try to introduce duplicate keys, the last one will overwrite the previous ones.\n", "\n", "Unlike sets or tuples, dictionaries are **changeable** - we can change, remove, or add items after a dictionary has been created. Look at the code below. Before running it, try to predict what the outcome dictionary will be." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "d = {\n", " \"name\": \"hemoglobin\",\n", " \"organism\": \"human\",\n", " \"length\": 142\n", "}\n", "\n", "# Changing an item\n", "d[\"length\"] = 151\n", "\n", "# Adding an item\n", "d[\"multimeric\"] = True\n", "\n", "# Removing an item using pop()\n", "d.pop(\"organism\")\n", "\n", "print(d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we want to quickly assess **how many items a dictionary has**, we can use the `len()` function:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "d = {\n", " \"name\": \"hemoglobin\",\n", " \"organism\": \"human\",\n", " \"length\": 142,\n", " \"multimeric\": True,\n", " \"subunits\": [\"alpha\", \"beta\"]\n", "}\n", "\n", "print(len(d))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You will see many applications of dictionaries in **bioinformatics**. For instance, you can imagine storing sequences with their IDs as keys and sequences as values:\n", "\n", "```\n", "sequences_dictionary = {\n", " \"seq_ID_1\": \"GTCCAGTGAC\",\n", " \"seq_ID_2\": \"TGGTACCGTA\",\n", " \"seq_ID_3\": \"TGCCGATAGG\"\n", "}\n", "```\n", "\n", "or storing information about genomic regions with chromosome names/regions as keys and coordinates as values:\n", "\n", "```\n", "genomic_coordinates_dictionary = {\n", " \"chr1:1000-2000\": {\"start\": 1000, \"end\": 2000, \"gene\": \"geneA\"},\n", " \"chr2:3000-4000\": {\"start\": 3000, \"end\": 4000, \"gene\": \"geneB\"}\n", "}\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "thebe-remove-input-init" ] }, "outputs": [], "source": [ "import micropip\n", "await micropip.install(\"jupyterquiz\")\n", "from jupyterquiz import display_quiz\n", "import json\n", "\n", "with open(\"questions5.json\", \"r\") as file:\n", " questions=json.load(file)\n", " \n", "display_quiz(questions, border_radius=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Set type\n", "\n", "In addition to lists, tuples and dictionaries, **set** is another built-in data type used to store collections of data.\n", "A set is an unordered collection of **unique** items; in other words, duplicate items are not allowed in a set. \n", "While items in a set are **unchangeable**, it is possible to **remove and add** items.\n", "\n", "Sets are written with curly brackets in Python, like this:\n", "```\n", "my_set = {\"dna\", \"rna\", \"protein\"}\n", "```\n", "\n", "Try it out:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "my_set = {\"dna\", \"rna\", \"protein\"}\n", "print(my_set)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What happens if you have a duplicate value? Try adding another \"dna\" item in the set above and run the code.\n", "\n", "It is often useful to know **how many** items are in the set. For this, you can use `len()`. Notice that one set may contain multiple data types." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "my_set = {\"dna\", \"rna\", \"protein\", False, 46, \"lipid\", \"carbohydrate\", True}\n", "print(len(my_set))" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-c1323d47dae023f1", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Converting types\n", "\n", "We can also **convert** a variable value from one type to another by using **functions**. These functions carry names of types that we want to convert to. See these examples:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "float(5)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "int(7.63)" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-e7f8cf2c018ef4fd", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "Note that when converting a `float` to an `int`, Python does not round off the value, but instead drops all the numbers after the decimal point (it \"truncates\" the floating point number). If we want to convert to an integer and round the value, we can use the `round()` function:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "b = round(7.63)\n", "print(b)\n", "\n", "print(type(b))\n", "print(b+0.4)" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-f3f5149b2d627e26", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "This works for conversions between many types. Sometimes, you will lose information in this process, for example, by converting a `float` to an `int`, we lose all the numbers after the decimal point. \n", "\n", "Sometimes, Python can't decide what to do, and so it triggers an error:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "float(1+1j)" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-582c3f589fac8746", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "A very useful feature is that Python can convert numbers into strings:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "a = 7.54\n", "str(a)\n", "b = a + 1\n", "print(b)\n", "\n", "print(type(a))\n", "print(type(b))" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-18152675870ab0f1", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "That is actually what happens when you use the `print()` command with a numeric value (as the output of `print()` is a printed text).\n", "\n", "As long as your string is easily convertible to a number, Python can do this for you too. Note below that the quotation marks make 5.74 a string." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "float('5.74')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "int('774')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "complex('5+3j')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also convert immutable tuples to mutable lists and back again:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "a = (4,5)\n", "print(type(a))\n", "\n", "a = list(a)\n", "print(type(a))\n", "\n", "a = tuple(a)\n", "print(type(a))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also make several type changes in one go. For instance, the following code will first convert floating point number 5.1 into integer using the **inner function** `int()`, and then convert integer into string with the **outer function** `str()`. The outcome will, therefore, be string." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "a = str(int(5.1))\n", "print(a)\n", "print(type(a))" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-ce079e7a0832a0f5", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "```{exercise}\n", ":class: dropdown\n", "Define a list of variables, each of a different type. You can name them `a`, `b`, etc. Define variables of as many different types as possible, i.e., all the examples from above and maybe a few more. Try to change their type, and then run the `type()` function to see what the effect is. \n", "1. Were all conversions possible? \n", "2. What did you observe in converting `bool` into `int`, and the other way around?\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "lines_to_next_cell": 0, "tags": [ "remove-output" ] }, "outputs": [], "source": [ "# Your code here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{exercise}\n", ":class: dropdown\n", "Define a list that contains some duplicate elements. Try to convert it to a set using `set()`. What does your set look like compared to the list? Use the cell below to write your code.\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "remove-output" ] }, "outputs": [], "source": [ "# Your code here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "thebe-remove-input-init" ] }, "outputs": [], "source": [ "import micropip\n", "await micropip.install(\"jupyterquiz\")\n", "from jupyterquiz import display_quiz\n", "import json\n", "\n", "with open(\"questions2.json\", \"r\") as file:\n", " questions=json.load(file)\n", " \n", "display_quiz(questions, border_radius=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Names of variables\n", "\n", "So far we have not talked about the names of variables. On this page, we used names such as `a` and `b` for variables. Each time, the previous value of the variable carrying the same name was overwritten. Furthermore, what does `a` refer to? Is it acceleration, a coefficient?\n", "\n", "If you want to be able to read your code next year, or if you want to be able to read your code, you have to come up with proper names for your variables. \n", "We discuss variable names and other tips and conventions in the next chapter ([good coding practices](../chapter5/good-coding-practices.ipynb) and [PEP 8 style guidelines for Python](../chapter5/pep-8.ipynb))." ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-53972ca5ec4efa32", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Tab completion\n", "\n", "Computer programmers often forget things, and often they forget variables they have defined. Also, programmers like to save typing whenever they can. \n", "\n", "For this reason, you can use the feature called **Tab completion**. Recall that the Tab completion also workes in the terminal. \n", "\n", "The idea is that if you start typing part of the name of a variable or part of the name of a function, and then push the `Tab` key, VS Code will bring up a list of the variable and function names that match what you have started to type. If ony one matches, it will automatically type the rest for you. If multiple things match, it will offer you a list: you can either keep typing until you type something that is unique and then press `Tab` again, or you can use the cursor keys to select what you want.\n", " \n", "Try this in VS Code." ] } ], "metadata": { "jupytext": { "formats": "ipynb,md" }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.4" } }, "nbformat": 4, "nbformat_minor": 4 }