{"cells":[{"cell_type":"markdown","metadata":{"id":"13i366s9TGnS"},"source":["<br>\n","\n","# Module 1 - Python basics <a id='0'></a>\n","--------------------------\n","Material Sources retrieved from **[Swiss Institute of Bioinformatics](https://www.sib.swiss)** with modified from GSI Team"]},{"cell_type":"markdown","metadata":{"id":"I-6EmyANTGnc"},"source":["### Table of Content <a id='toc'></a>\n","\n","[**Python basics**](#0)  \n","&nbsp;&nbsp;&nbsp;&nbsp;[Variables](#1)  \n","&nbsp;&nbsp;&nbsp;&nbsp;[Code indentation - the importance of white spaces in Python](#2)  \n","&nbsp;&nbsp;&nbsp;&nbsp;[Functions](#3)  \n","&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[The help function - your best friend in Python](#4)  \n","&nbsp;&nbsp;&nbsp;&nbsp;[Reading and understanding errors](#5)  \n","&nbsp;&nbsp;&nbsp;&nbsp;[Micro Exercise 1](#6)  \n","\n","[**Object types: simple types**](#7)  \n","&nbsp;&nbsp;&nbsp;&nbsp;[Type conversion](#8)  \n","&nbsp;&nbsp;&nbsp;&nbsp;[Micro Exercise 2](#9)  \n","&nbsp;&nbsp;&nbsp;&nbsp;[Operators](#10)  \n","&nbsp;&nbsp;&nbsp;&nbsp;[Arithmetic operators](#11)  \n","&nbsp;&nbsp;&nbsp;&nbsp;[Comparison operators](#12)  \n","&nbsp;&nbsp;&nbsp;&nbsp;[Micro Exercise 3](#13)\n","\n","[**Object types: container types**](#14)  \n","&nbsp;&nbsp;&nbsp;&nbsp;[**Strings**](#15)  \n","&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Length of a string](#16)  \n","&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[String concatenation](#17)  \n","&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[String slicing](#18)  \n","&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Micro exercise 4](#19)  \n","\n","&nbsp;&nbsp;&nbsp;&nbsp;[**Lists and tuples**](#20)  \n","&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[List and tuple slicing](#21)  \n","&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Mutability - an important difference between lists and tuples](#22)  \n","&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Manipulating lists: adding and removing elements](#23)  \n","&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[From list to string, and back again ...](#24)  \n","&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Micro Exercise 5](#25)\n","\n","&nbsp;&nbsp;&nbsp;&nbsp;[**Dictionaries**](#26)\n","\n","[**Additional Theory**](#28)  \n","&nbsp;&nbsp;&nbsp;&nbsp;[Mutability of objects in Python](#29)  "]},{"cell_type":"markdown","metadata":{"id":"SSi69Aa0TGne"},"source":["\n","## Python documentation and learning resources\n","\n","* **Official [python documentation](https://www.python.org/doc/)**: this is the official python documentation, as well as some tutorials.\n","* **[Alternative documentation](https://www.w3schools.com/python/python_reference.asp)**: reference for built-in functions and types (sometimes easier or more complete than the `help()` function)."]},{"cell_type":"markdown","metadata":{"id":"pZdNW4Q8TGnf"},"source":["<div class=\"alert alert-block alert-info\">\n","    \n","## Primary Material\n","    \n","</div>"]},{"cell_type":"markdown","metadata":{"id":"tGTF_tGfTGnf"},"source":["\n","## Python basics\n","---------------------\n","\n","### Variables <a id='1'></a>\n","In python, as in many programming language, **objects are stored in variables**.\n","* A value is **assigned** to a variable using the **`=`** sign.\n","* **Important:** unlike in mathematics, the `=` sign in python is directional: the variable name must\n","  always be on the left of the `=`, and the value to assign to the variable on the right.  \n","\n","  Example:\n","  ```python\n","  a = 23    # Valid assignment.\n","  8 = b     # NOT a valid assignment.\n","  ```\n","\n","<br>\n","\n","When we create a variable, python associates the variable name to a section of your computer's memory (i.e. the [RAM](https://en.wikipedia.org/wiki/Random-access_memory)) which will contain the data for the variable.\n","\n","<img src=\"https://github.com/sib-swiss/first-steps-with-python-training/raw/master/notebooks/img/var_simple.png\" alt=\"representation of a simple variable in memory\" style=\"width:150px;\" />\n","\n","\n","In python, variables names must adhere to these restrictions:\n","* Variable names must be **composed solely of uppercase and lowercase letters** (`A-Z`, `a-z`),\n","  **digits** (`0-9`), and the **underscore** character `_`.\n","* The **first character** of a variable name **cannot be a digit**.\n","* By convention, **variable names starting with a single or double underscore `_`/`__` are reserved\n","  for \"special\" variables** (class private attributes, \"magic\" variables).\n","* Examples:\n","    * `var_1` is a valid variable name.\n","    * `1_var` is **not** a valid name (starts with a digit)\n","    * `var-1` is **not** a valid name (contains a the non-authorized character `-`)\n","    * `__var_1__` is valid, but **should not be used**, with the exception of very specific situations.\n","\n","<br>\n","\n","**Important tips**:\n","* Using **explicit variable names makes your code easier to read** for others, and possibly yourself\n","  in a not-so-distant future.  \n","  E.g. `input_file` is better than `iptf`, even if it is a bit longer.\n","* **Never use python built-in names as variable names**, otherwise you will overwrite this object in the\n","  namespace.  \n","  E.g., don't call a variable `str`, `int` or `list` (this can be painful to debug)."]},{"cell_type":"code","execution_count":null,"metadata":{"scrolled":true,"id":"lNZLKTf6TGng","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687835923791,"user_tz":-420,"elapsed":294,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"5bf468ab-8e2a-41eb-e2dd-c7d0e6d17918"},"outputs":[{"output_type":"stream","name":"stdout","text":["35\n","hello python new\n","hello python new\n"]}],"source":["my_variable = 35        # Assign the value 35 to the variable name \"my_variable\".\n","var_a = \"hello python new\"  # Assign the value \"hello python\" to variable \"var_a\".\n","var_b = var_a           # Assign the value of \"var_a\" to \"var_b\".\n","\n","# By the way, text located after a \"#\" character - just like this line - are \"comments\".\n","# Comments is text that will not be executed, but is useful for code documentation.\n","print(my_variable)\n","print(var_a)\n","print(var_b)"]},{"cell_type":"code","source":["my_name = 'Faris Izzatur Rahman'"],"metadata":{"id":"t-_0jb1J3JkS"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":[],"metadata":{"id":"75GKm5SL3r2p"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"ad_mb0JfTGni"},"source":["<div class=\"alert alert-block alert-info\">\n","    \n","## Primary Material\n","    \n","</div>"]},{"cell_type":"markdown","metadata":{"id":"msNXx8LvTGnj"},"source":["<br>\n","\n","[Back to ToC](#toc)\n","\n","### Code indentation - the importance of white spaces in Python <a id='2'></a>\n","\n","**Indentation** is the number of **white spaces before the first text element** (on a given line).\n","\n","```python\n","    |var_1 = 2\n","    | var_1 = 2\n","     ^\n","    # The line above is indented by 1 space.\n","    \n","    |  var_1 = 2\n","     ^^\n","    # The line above is indented by 2 spaces.\n","```\n","\n","* Unlike many other languages, **indentation has a very important meaning in python**: it is used\n","  to define a so-called **\"code block\"** (more on that later in the course).\n","* Using proper **indentation is an integral part of python** - unlike most other languages where it's\n","  just good practice.\n","* When outside of a \"code block\", there should be no indentation on the line.\n","* A wrong level of indentation will trigger an `IndentationError`.\n","* Comments can have any level indentation."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"_Wmrbz2uTGnk","colab":{"base_uri":"https://localhost:8080/","height":135},"executionInfo":{"status":"error","timestamp":1687836150821,"user_tz":-420,"elapsed":335,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"169b54a4-6de9-4499-8e37-2d5a94ba1d83"},"outputs":[{"output_type":"error","ename":"IndentationError","evalue":"ignored","traceback":["\u001b[0;36m  File \u001b[0;32m\"<ipython-input-4-9bdaf1f82a21>\"\u001b[0;36m, line \u001b[0;32m2\u001b[0m\n\u001b[0;31m    var_1 = \"abc\"   # unexpected indentation (i.e. outside of a code block) -> IndentationError\u001b[0m\n\u001b[0m    ^\u001b[0m\n\u001b[0;31mIndentationError\u001b[0m\u001b[0;31m:\u001b[0m unexpected indent\n"]}],"source":["var_1 = \"abc\"    # No indentation -> valid syntax.\n"," var_1 = \"abc\"   # unexpected indentation (i.e. outside of a code block) -> IndentationError\n","\n","     # Comment lines, however, can be indented as you wish."]},{"cell_type":"markdown","metadata":{"id":"IAL_UiYmTGnl"},"source":["When assigning a variable, white spaces after the variable name do not matter. However the [Python style convention](https://www.python.org/dev/peps/pep-0008/#whitespace-in-expressions-and-statements) is to have **exactly 1 space** on each side of the `=` operator when assigning a variable.\n"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"l3snCKhETGnl","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687836206402,"user_tz":-420,"elapsed":353,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"4374b66d-3311-45a9-bdd9-aab82a6aec01"},"outputs":[{"output_type":"stream","name":"stdout","text":["abc\n"]}],"source":["var_1 = \"abc\"                   # Valid syntax and good style.\n","var_1           =        \"abc\"  # Valid syntax but bad style -> please avoid.\n","print(var_1)"]},{"cell_type":"markdown","metadata":{"id":"vlKurFMATGnm"},"source":["<br>\n","\n","[Back to ToC](#toc)\n","\n","### Functions <a id='3'></a>\n","Another very important concept in Python - as in most programming language - are **functions**:\n","* Functions are **re-usable blocks of code** that have been given a name and are designed to perform an action.\n","  How to define your own functions will be covered in Module 2 of this course.\n","* Functions can be written to perform anything, from the simplest task to the most complex.\n","* To **call a function**, one uses its name followed by parentheses `()`, which can contain an eventual set of\n","  **arguments**.\n","* Values passed to functions are called **arguments**, they can be **mandatory** (positional arguments)\n","  or **optional** (keyword arguments).\n","\n","**Example:** to call the \"print\" function, we type `print()` and pass the text to print inside the `()`.\n","  "]},{"cell_type":"code","execution_count":null,"metadata":{"id":"y6jP_6J7TGnm"},"outputs":[],"source":["print(\"This\", \"will\", \"be\", \"printed\")\n","print(\"This\", \"will\", \"be\", \"printed\", sep=\"--\")"]},{"cell_type":"markdown","metadata":{"id":"5gBdnWxyTGnm"},"source":["<div class=\"alert alert-block alert-warning\">\n","\n","**Tips in Python**\n","    \n","</div>"]},{"cell_type":"markdown","metadata":{"id":"ShFA6tirTGnm"},"source":["<br>\n","\n","[Back to ToC](#toc)\n","\n","#### The help function - your best friend in Python <a id='4'></a>\n","In python, almost any object or function is extensively documented: what it is, what it does, how to use it, ...  \n","This information is accessed using the `help()` function, which takes as argument the object we want to get help with.\n","\n","Let's try to look up the help page of the `print()` function that we encountered moments ago:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Bc509XnfTGnm"},"outputs":[],"source":["help(print)"]},{"cell_type":"markdown","metadata":{"id":"sa6xCJjQTGnn"},"source":["**It tells us that:**\n"," * `print` is a function (more specifically a **built-in** function).\n"," * It gives a description of what `print()` does:\n","\n","   > Prints the values to a stream, or to sys.stdout by default.\n","   \n","   So the function prints the values that are passed to it to the console (or possibly to a file).\n"," * It takes one or more positional (mandatory) arguments `value`, which are the things that will be printed.\n","   The fact that multiple `value` arguments can be passed is indicated by the `...`.\n"," * It has 4 optional keyword arguments that refine its use (e.g. `sep` and `end`).\n"," * The **default values** for the keyword arguments are shown in the function's signature:\n","\n","    > print(value, ..., sep=' ', end='\\n', file=sys.stdout, flush=False)\n","\n","<br>\n","\n","Let's try to apply our new knowledge of the `print` function :"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"2Ise-vHcTGnn"},"outputs":[],"source":["print(\"test\")                                         # Simple usage.\n","print(\"Please collect\" , 42, \"Shrubberies\")           # We can make it print several values. by default, they are separated by 1 space.\n","print(\"Please collect\" , 42, \"Shrubberies\", sep=\"/\")  # The \"sep\" argument can be used to change the separator between values.\n","\n","print(\"first line\", end=\"\")  # The 'end' argument can be used to modify the character printed at the end\n","                             # of each line. It defaults to \"\\n\", the new line character.\n","print(\"second line\")"]},{"cell_type":"markdown","metadata":{"id":"v6Xfv_VwTGnn"},"source":["<br>\n","\n","**Don't hesitate to use the `help` function on any object (e.g. functions) to understand how they work.**"]},{"cell_type":"markdown","metadata":{"id":"wWcnxhypTGnn"},"source":["[Back to ToC](#toc)\n","\n","### Reading and understanding errors <a id='5'></a>\n","\n","Unless you are a perfect human being, your code will contain errors at some point.  \n","Errors ~~can sometimes be~~ are frustrating, but they are unavoidable, and the best way to correct them is to actually read and try to understand them.\n","\n","Here is an error example:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"J_ro4XmCTGnn","colab":{"base_uri":"https://localhost:8080/","height":207},"executionInfo":{"status":"error","timestamp":1687836305466,"user_tz":-420,"elapsed":329,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"ada95b5b-850b-48ef-8823-59cf000e6bdf"},"outputs":[{"output_type":"error","ename":"NameError","evalue":"ignored","traceback":["\u001b[0;31m---------------------------------------------------------------------------\u001b[0m","\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)","\u001b[0;32m<ipython-input-6-2b2a28d3d859>\u001b[0m in \u001b[0;36m<cell line: 3>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0mvar_a\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m42\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0mvar_b\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvar_a\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvar_c\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m","\u001b[0;31mNameError\u001b[0m: name 'var_c' is not defined"]}],"source":["var_a = 42\n","var_b = var_a + 3\n","print(var_c)"]},{"cell_type":"markdown","metadata":{"id":"5WNmD1TNTGnn"},"source":["The python error message gives us a number of useful info:\n","* The first line indicates the **type** of the error. In our example we got a `NameError`, meaning that\n","  a name (of an object) has not been found, which means that there is no variable/function/class with said\n","  name currently defined. If you want to know more about a certain error type, you can use the help\n","  function on it: `help(NameError)`.\n","* The following lines indicate **where the error occurred**, which is very useful when there are hundreds of\n","  lines in your code. Here the error occurred on line `3` (as indicated by the arrow `----> 3`).\n","* Finally, we have the **error message**: `NameError: name 'var_c' is not defined`. This points out\n","  that we tried to print the variable `var_c` when that variable does not exist (i.e., that name\n","  is not defined).\n","\n","> <span style=\"color:blue\">Arguably, being able to **read and understand errors** and being able to **read the help** accounts for ~50% of \"coding skills\"...</span>."]},{"cell_type":"markdown","metadata":{"id":"v0fXNbB7TGno"},"source":["<div class=\"alert alert-block alert-success\">\n","    \n","### Micro Exercise 1 <a id='6'></a>\n","* Copy/paste the line below in a code cell and execute it.\n","    ```python\n","    a = 10\n","    42 + \"a\"\n","    ```\n","    <br>\n","    \n","* Look at the error that was raised. Try to understand it, and modify the code to fix it.\n","\n","<div>\n"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"iXS8UI1yTGno","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687836540610,"user_tz":-420,"elapsed":4,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"d33931fc-750b-4f90-8329-4fcd74119e5e"},"outputs":[{"output_type":"execute_result","data":{"text/plain":["52"]},"metadata":{},"execution_count":9}],"source":["a = 10\n","42 + a"]},{"cell_type":"markdown","metadata":{"id":"tNKv2aU9TGno"},"source":["[Back to ToC](#toc)\n","\n","## Object types: simple types <a id='7'></a>\n","\n","**Everything in python is an object**, and each objects is of a specific **type** (the type is the class of the object).\n","\n","There exist plenty of types (it is even common to define your own new type), but there are a few very common ones - known as **built-in** types - that you ought to know:\n","\n","* **`bool`**: boolean/logical values, either `True` or `False`, like 0 or 1.\n","* **`int`**: integer number.\n","* **`float`**: floating point number (numbers with a decimal fraction).\n","\n","To know the type of an object, we can make use of the **`type()`** function.  \n"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"7veFESzhTGno","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687836418762,"user_tz":-420,"elapsed":322,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"bebe94c0-6477-4e12-9f3e-8683ce1616c5"},"outputs":[{"output_type":"stream","name":"stdout","text":["<class 'bool'>\n","<class 'int'>\n","<class 'str'>\n","<class 'builtin_function_or_method'>\n"]}],"source":["print(type(True))\n","print(type(11))\n","print(type(\"hello world\"))\n","print(type(print))"]},{"cell_type":"markdown","metadata":{"id":"idEgoiDdTGno"},"source":["**A few comments about types in python:**\n","* Python is (by default\\*\\*) a **dynamically typed** language (as opposed to **statically typed**\n","  languages such as C or C++ e.g.). This means that variables are declared without a specific type,\n","  and the type is assigned based on what object is assigned to the variable.  \n","  This has its advantages (easier and faster to write code) and downsides (e.g. type error bugs can\n","  remain hidden for a long time until they are triggered by some unusual input data).\n","\n","  \\*\\* Starting with python 3.6, it is possible (as an option) to add **type annotations** for\n","  variables, but these are not enforced at runtime.\n","  \n","  <br>\n","  \n","* A corollary is that variables in Python are not restricted to a single type and can be reassigned\n","  another type of value at any time.\n","\n","**Example:** here we successively assign different values and types to the variable `a`."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"WkZrclU4TGno","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687836594794,"user_tz":-420,"elapsed":304,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"25982e0f-710c-4ef6-b1f2-9a3ed419d8e9"},"outputs":[{"output_type":"stream","name":"stdout","text":["Type of a is now: <class 'bool'>\n","Type of a is now: <class 'float'>\n","Type of a is now: <class 'int'>\n"]}],"source":["# Boolean\n","a = True\n","print(\"Type of a is now:\", type(a))\n","\n","# Float\n","a = 4.2\n","print(\"Type of a is now:\", type(a))\n","\n","# Integer\n","a = 42\n","print(\"Type of a is now:\", type(a))"]},{"cell_type":"markdown","metadata":{"id":"gMVFpt1UTGnp"},"source":["[Back to ToC](#toc)\n","\n","### Type conversion <a id='8'></a>\n","\n","Converting from one type to another is (often) fairly easy: just use the type name as a function.\n","\n","**Example:** convert an integer to a float."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"v0MgWqS_TGnp"},"outputs":[],"source":["a = 42\n","print(\"Type of 'a' before conversion:\", type(a), \", a = \", a)\n","\n","a = float(a)\n","print(\"Type of 'a' after conversion:\", type(a), \", a = \", a)"]},{"cell_type":"markdown","metadata":{"id":"-CTgUyzATGnp"},"source":["**Example:** convert to string"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"ZZvM1BEjTGnp"},"outputs":[],"source":["a = str(a)\n","print(\"Type of 'a' after conversion:\", type(a), \", a = \", a)"]},{"cell_type":"markdown","metadata":{"vscode":{"languageId":"python"},"id":"Joa97FTQTGnp"},"source":["Converting to string is useful when concatenating a string and a number:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"XKtHupUqTGnp"},"outputs":[],"source":["# This fails, because we cannot add strings and integers types.\n","print(\"This will fail, \" + 2 + \" bad\")"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"w5-4QiHbTGnq"},"outputs":[],"source":["# This works, because we convert the integer 4 to a string \"4\" before the concatenation.\n","print(\"This will work \" + str(4) + \" sure\")"]},{"cell_type":"markdown","metadata":{"id":"wzooC1rCTGnq"},"source":["<div class=\"alert alert-block alert-success\">\n","\n","### Micro Exercise 2 <a id='9'></a>\n","* Set `a = \"42\"`, then convert `a` back to an integer (`int`). Look up the `help` for integers.  \n","* If you have time, try to now set `a = \"42.0\"` and do the type conversion. Does it still work? If not, how\n","  can you fix the issue?\n","\n","<div>"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Ch4-C9IPTGnq"},"outputs":[],"source":[]},{"cell_type":"markdown","metadata":{"id":"4W2I_-qoTGnq"},"source":["<div class=\"alert alert-block alert-info\">\n","    \n","## Primary Material\n","    \n","</div>"]},{"cell_type":"markdown","metadata":{"id":"mhkCNaG3TGnq"},"source":["[Back to ToC](#toc)\n","\n","## Operators <a id='10'></a>\n","Now that we have variables containing objects of a certain **type**, we can begin to manipulate them using **operators**.\n","<br>\n","\n","### Arithmetic operators  <a id='11'></a>\n","You know most of these already:"]},{"cell_type":"code","execution_count":null,"metadata":{"scrolled":true,"id":"UgaPyMoUTGnv","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687836706462,"user_tz":-420,"elapsed":332,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"ad98e8ab-b952-419f-e03e-d77bdbb1ff66"},"outputs":[{"output_type":"stream","name":"stdout","text":["10\n","-3.9\n","10\n","2.5\n","16\n","2\n","1\n","248.5\n"]}],"source":["print( 3 + 7 )      # + : addition\n","print( 1.1 - 5 )    # - : subtraction\n","print( 5 * 2 )      # * : multiplication\n","print( 5 / 2 )      # / : division\n","print( 2 ** 4 )     # **: power\n","print( 5 // 2 )     # //: integer division (only the integer part of the quotient is kept,\n","                    #     the fractional part is discarded: 2.5 -> 2)\n","print( 5 % 2 )      # % : modulus = remainder of the integer division: 5 % 2 -> 1\n","\n","# As you would expect, variables can be used with opperators as well:\n","x = 4\n","y = 16 * x**2 - 2 * x + 0.5\n","print(y)"]},{"cell_type":"markdown","metadata":{"id":"GPY3D7vWTGnv"},"source":["[Back to ToC](#toc)\n","\n","### Comparison operators <a id='12'></a>\n","\n","These operators return a `bool` value: `True` or `False`."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"UTChdrA6TGnv","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687836765268,"user_tz":-420,"elapsed":652,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"b93b873e-0b66-4497-aee1-2a297e966951"},"outputs":[{"output_type":"stream","name":"stdout","text":["is a equal to 1?: False\n","is a different to 13.37?: True\n","is a greater than 5?: False\n","is a lower than 10?: True\n","is a above 5?: True\n","is a lower than 10?: True\n"]}],"source":["a = 5\n","print(\"is a equal to 1?:\", a == 1)              # == : equality\n","print(\"is a different to 13.37?:\", a != 13.37)  # != : inequality\n","print(\"is a greater than 5?:\", a > 5 )          # >  : larger than\n","print(\"is a lower than 10?:\", a < 10 )          # <  : lower than\n","print(\"is a above 5?:\", a >= 5 )                # <= : lower or equal\n","print(\"is a lower than 10?:\", a <= 10 )         # >= : larger or equal"]},{"cell_type":"markdown","metadata":{"id":"JnWwCILzTGnw"},"source":["**Warning:** comparisons are type-sensitive, so the following expression evaluates to `False`:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"uyg_8okpTGnx","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687836770547,"user_tz":-420,"elapsed":568,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"aa1c48da-5389-4661-cd27-992d8ff0d01d"},"outputs":[{"output_type":"stream","name":"stdout","text":["False\n"]}],"source":["a = 5\n","print(a == \"5\")"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"jUu5sB3VTGnx","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687836772839,"user_tz":-420,"elapsed":7,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"8ef8ed99-e41f-4653-b08b-c919613b9f70"},"outputs":[{"output_type":"stream","name":"stdout","text":["True\n"]}],"source":["print(a == 5.0)"]},{"cell_type":"markdown","metadata":{"id":"kLY85CNfTGnx"},"source":["Combine Operator"]},{"cell_type":"markdown","metadata":{"id":"qeXd0NlpTGny"},"source":["Boolean values (the result from a comparison) can be:\n","* **Combined** using `and` or `or`:\n","\n","    | Combining with `and` | **True** | **False** |\n","    |----------------------|----------|-----------|\n","    | **True**             | True     |  False    |\n","    | **False**            | Flase    |  False    |\n","  \n","    | Combining with `or`  | **True** | **False** |\n","    |----------------------|----------|-----------|\n","    | **True**             | True     |  True     |\n","    | **False**            | True     |  False    |\n","  \n","  <br>\n","  \n","* **Inverted** using `not`: `True` becomes `False`, and `False` becomes `True`."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"kqu89UwXTGny"},"outputs":[],"source":["a = 5\n","print(\"'and' requires both elements to be True:\" , True and ( 1 + 1 != 2 ) )\n","print(\"'or' requires at least element to be True:\" , ( a * 2 > 10 ) or ( a > 0 ) )\n","print(\"'not' inverses a boolean value! This is simply\", not False)"]},{"cell_type":"markdown","metadata":{"id":"jiQSgZKDTGnz"},"source":["<div class=\"alert alert-block alert-success\">\n","\n","### Micro Exercise 3 <a id='13'></a>\n","* Compute the product of 348 and 157.2.\n","* Use a comparison operator to check if the result is larger than 230 square (`230 ** 2`)\n","\n","<div>"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"AmKm0DVRTGnz"},"outputs":[],"source":[]},{"cell_type":"markdown","metadata":{"id":"oCub16BxTGnz"},"source":["<div class=\"alert alert-block alert-info\">\n","    \n","## Primary Material\n","    \n","</div>"]},{"cell_type":"markdown","metadata":{"id":"tCGz7Vd7TGnz"},"source":["[Back to ToC](#toc)\n","\n","## Object types: container types <a id='14'></a>\n","\n","These built-in types are object that contain other objects.  \n","They are also known as **iterables**, because one can iterate over them using e.g. a `for` loop (see Notebook 2 of this course):\n","* **`str`**: string - text.\n","* **`list`**: **mutable** list of objects (mutable = can be modified after it was created).\n","* **`tuple`**: **immutable** list of objects (immutable = cannot be modified after it was created).\n","* **`dict`**: dictionary associating 'key' to 'value'.\n","\n","Containers objects have a dedicated **`[]`** operator that lets user access one - or several - of the object they contain.  \n","In addition, the number of objects a container has (its length) can be accessed using the **`len()`** function.\n","\n","**Important:** in python (unlike e.g. in R), **indexing is zero-based**. This means that the first element of a container type object is accessed with `object[0]`, and not `object[1]`."]},{"cell_type":"markdown","metadata":{"id":"TBYY_EpTTGnz"},"source":["## Strings <a id='15'></a>\n","In python, the **`string`** type is a **sequences of characters** that can be used to represent text of any length.\n","\n","* Strings can be declared using either **single `'`** or **double `\"`** quotes."]},{"cell_type":"code","execution_count":null,"metadata":{"scrolled":true,"id":"SOv6st28TGn0"},"outputs":[],"source":["gene_seq = \"ATGCGACTGATCGATCGATCGATCGATGATCGATCGATCGATGCTAGCTAC\"\n","name = 'Sir Lancelot of Camelot'\n","print(gene_seq)\n","print(name)"]},{"cell_type":"markdown","metadata":{"id":"5kGEC3o2TGn0"},"source":["In memory, this variable can be represented as follow:\n","\n","<img src=\"https://github.com/sib-swiss/first-steps-with-python-training/raw/master/notebooks/img/var_str1.png\" alt=\"representation of a string variable in memory\" style=\"width:250px;\" />\n","\n","Remember that strings are *container* variables, that is why we represent each letters as different elements.\n","\n","Each element is associated an **index**, starting at 0.\n","\n","<img src=\"https://github.com/sib-swiss/first-steps-with-python-training/raw/master/notebooks/img/var_str2_with_indexes.png\" alt=\"representation of a string variable in memory with indexes\" style=\"width:250px;\" />\n"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"aFY1jF_1TGn1"},"outputs":[],"source":["my_str = \"text\"\n","print(\"The second element of the string is:\", my_str[1])"]},{"cell_type":"markdown","metadata":{"id":"msa-UtVATGn1"},"source":["<div class=\"alert alert-block alert-warning\">\n","\n","**Tips in Python**\n","    \n","</div>"]},{"cell_type":"markdown","metadata":{"id":"d-gWHcUITGn1"},"source":["* **Triple quotes** can be used to define multi-line strings."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"IhOJZYBRTGn2"},"outputs":[],"source":["long_string = \"\"\"Let me tell you something, my lad.\n","When you’re walking home tonight and some great\n","homicidal maniac comes after you with a bunch\n","of loganberries, don’t come crying to me!\\n\"\"\"\n","print(long_string)"]},{"cell_type":"markdown","metadata":{"id":"p73jDT_tTGn2"},"source":["* **Accented and special characters** are possible in strings. In example:\n","  * **`\\t`** = tab\n","  * **`\\n`** = new line"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"p6cC8YdmTGn3"},"outputs":[],"source":["my_quote = \"\"\"Gracieux : « aimez-vous à ce point les oiseaux\n","que paternellement vous vous préoccupâtes\n","de tendre ce perchoir à leurs petites pattes ? »\\n\"\"\"\n","print(my_quote)\n","\n","# Example of inserting a tab/new line in a string:\n","print('Hello\\tWorld')  # \\t : tabulation\n","print('Hello\\nWorld')  # \\n : newline"]},{"cell_type":"markdown","metadata":{"id":"eI1Q5q-HTGn3"},"source":["**Question:** why do these 2 lines print exactly the same text?"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"MRwlXk-tTGn3"},"outputs":[],"source":["print('Hello World')\n","print('Hello World\\n', end=\"\")"]},{"cell_type":"markdown","metadata":{"id":"0t0s_lYcTGn3"},"source":["* **Combining** single and double quotes."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"QRHWivirTGn4"},"outputs":[],"source":["quote_in_quote_1 = \"Let me tell you 'something', my lad\"\n","quote_in_quote_2 = 'Let me tell you \"something\", my lad'\n","print(quote_in_quote_1)\n","print(quote_in_quote_2)\n","\n","# Note: quotes can also be escaped, but it is a bit less readable than using different quote types.\n","quote_in_quote_3 = \"Let me tell you \\\"something\\\", my lad\"\n","print(quote_in_quote_3)"]},{"cell_type":"markdown","metadata":{"id":"1FE5pTBqTGn4"},"source":["<div class=\"alert alert-block alert-info\">\n","    \n","## Primary Material\n","    \n","</div>"]},{"cell_type":"markdown","metadata":{"id":"HNtnQgb9TGn4"},"source":["\n","### Length of a string <a id='16'></a>\n","The **`len()`** function can be used on a string to return its length:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"4XHn4RK7TGn4","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687837733476,"user_tz":-420,"elapsed":6,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"fe80cccf-5a6e-40d5-ce39-834863d36c9e"},"outputs":[{"output_type":"stream","name":"stdout","text":["The number of characters in the string 'Faris Izzatur Rahman' is: 20\n"]}],"source":["name = 'Sir Lancelot of Camelot!!12345'\n","print(\"The number of characters in the string '\", my_name, \"' is: \", len(my_name), sep='')"]},{"cell_type":"markdown","metadata":{"id":"bX3NDQS0TGn4"},"source":["### String concatenation <a id='17'></a>\n","* Strings can be concatenated with the **`+`** operator.\n","* Strings can be \"multiplied\" (i.e., repeatedly concatenated) with the **`*`** operator."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Le1nTNcWTGn5"},"outputs":[],"source":["print(\"dead\" + \"-\" + \"parrot\")\n","print(\"spam \" * 5)"]},{"cell_type":"markdown","metadata":{"id":"KFW7ycsATGn5"},"source":["<div class=\"alert alert-block alert-info\">\n","    \n","## Primary Material\n","    \n","</div>"]},{"cell_type":"markdown","metadata":{"id":"_wdCTYOQTGn5"},"source":["### String slicing <a id='18'></a>\n","\n","Because strings are a type of sequence (a sequence of characters), the different characters of a string can be accessed using the **`[]` operator**, with the index of the desired element(s).  \n","\n","<img src=\"https://github.com/sib-swiss/first-steps-with-python-training/raw/master/notebooks/img/var_str3_with_indexes_and_access.png\" alt=\"representation of a string variable in memory with indexes and access to an element\" style=\"width:250px;\" />\n","\n","<br>\n","\n","* Remember that in python, the index of the first element is `[0]`.\n","* Negative indices will access characters starting from the end of the string. E.g. `[-1]` returns the\n","  last character in the string.\n","  \n","<img src=\"https://github.com/sib-swiss/first-steps-with-python-training/raw/master/notebooks/img/var_str3_with_indexes_and_reverse_access.png\" alt=\"representation of a string variable in memory with indexes and access to an element using reverse indexing\" style=\"width:400px;\" />\n","  "]},{"cell_type":"code","execution_count":null,"metadata":{"id":"lG8k8_-tTGn6"},"outputs":[],"source":["my_string = \"And now, something completely different.\"\n","print(\"The first element of this string is:\", my_string[0] )  # 0 is the index of the 1st element of the string.\n","print(\"The 5th element of this string is:\", my_string[4] )    # 5th element of the string.\n","print(\"The last element of this string is:\", my_string[-1] )  # -1 is the index of the last element of the string."]},{"cell_type":"markdown","metadata":{"id":"hgr1gJphTGn6"},"source":["Indices can also be used to retrieve several elements at once: this is called a **slice operation** or **slicing**:\n","* The general syntax of slicing is `[start index: end index (excluded): step]`\n","* The end index position is **excluded from the slice**.\n","* The **default step value is 1**. It can be omitted (and very often is).\n","* If the start index is omitted, the slicing is implicitly done from the beginning of the string. `string[:10]`\n","* If the end index is omitted, the slicing is implicitly done until the end of the string. `string[10:]`"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"OTaM3zQtTGn6","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687838227841,"user_tz":-420,"elapsed":4,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"3ccf92ff-09fd-421b-d2aa-19d2ed6986a2"},"outputs":[{"output_type":"stream","name":"stdout","text":["And now, something completely different.\n","And n\n","And n\n","ow, something completely different.\n","o mhgole frt\n"]}],"source":["my_string = \"And now, something completely different.\"\n","print(my_string)\n","print(my_string[0:5])   # Slice operation: get all elements from index 0 (included) to index 5 (excluded)\n","print(my_string[:5])    # Implicitly slices from the beginning of the string up to (but not included) index 5.\n","print(my_string[5:])    # Implicitly slices until the end of the string.\n","print(my_string[5::3])  # Keep every second letter, starting from index 5 to the end of the string."]},{"cell_type":"markdown","metadata":{"id":"ij8cIje4TGn6"},"source":["**Tip:** you can reverse a sequence (such as a string) by using the **`[::-1]`** slicing operation."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"xair98MrTGn6"},"outputs":[],"source":["print(my_string[::-1])  # Goes through the string from end to start -> reverses the string !"]},{"cell_type":"markdown","metadata":{"id":"48fuNiI9TGn7"},"source":["<div class=\"alert alert-block alert-success\">\n","\n","### Micro Exercise 4 <a id='19'></a>\n","* Create a string variable containing your name.\n","* Extract the last 3 letters from it using slicing.\n","\n","<div>"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"dCno5OXDTGn7","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687838725156,"user_tz":-420,"elapsed":5,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"3879fbd1-4462-4b24-9dd0-1ac2c13281fc"},"outputs":[{"output_type":"stream","name":"stdout","text":["man\n"]}],"source":["print(my_name[-3:])"]},{"cell_type":"code","source":["print(my_name.count('a'))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"SfS4MooYB7b-","executionInfo":{"status":"ok","timestamp":1687838865201,"user_tz":-420,"elapsed":540,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"154e054a-229e-40d2-818d-9c214193e54c"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["4\n"]}]},{"cell_type":"code","source":["seq = \"ATGCTAGTCGCGCTGTAGAGATAGTAGCGCTGCTAGATCGTAGAT\"\n","print(seq.count('A'))"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"g7a3d-oyCWHj","executionInfo":{"status":"ok","timestamp":1687838934920,"user_tz":-420,"elapsed":6,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"c0825f9f-fad4-441d-f690-d03ace91cab9"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["11\n"]}]},{"cell_type":"markdown","metadata":{"id":"Ajcv0QR9TGn7"},"source":["\n","[Back to ToC](#toc)\n","\n","## Lists and tuples <a id='20'></a>\n","\n","Lists and tuples are **sequence type** objects that can contain any type of elements (other objects).\n","* **Lists** are declared by surrounding a comma separated list of objects with **`[]`**.\n","* **Tuples** are declared similarly, but using **`()`**."]},{"cell_type":"markdown","metadata":{"id":"16myDJbMTGn7"},"source":["#### Create a list"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"J5lkpuhuTGn7","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687840318073,"user_tz":-420,"elapsed":369,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"04b5f9e2-01e4-440a-8577-9c7eb2a3315e"},"outputs":[{"output_type":"stream","name":"stdout","text":["The content of my_list is: ['item 0', 'item 1', 'item 2']\n","length of my list is: 3\n","\n","The content of my_list is: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]\n","length of my list is: 10\n"]}],"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","print(\"\\nThe content of my_list is:\", another_list)\n","print(\"length of my list is:\", len(another_list))"]},{"cell_type":"markdown","metadata":{"id":"DhoUr7X1TGn7"},"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."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Ug77KTwaTGn8","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687840432859,"user_tz":-420,"elapsed":391,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"4affcf29-0f27-4081-b085-4508b5f79097"},"outputs":[{"output_type":"stream","name":"stdout","text":["The content of my_list is: [1, 2, 'spam', 'eggs', 5.2, [2, 'spam']]\n","length of my list is: 6\n"]}],"source":["my_list = [1, 2, \"spam\", \"eggs\", 5.2, [2, \"spam\"]]\n","\n","print(\"The content of my_list is:\", my_list)\n","print(\"length of my list is:\", len(my_list))"]},{"cell_type":"markdown","metadata":{"id":"Aix5EWssTGn8"},"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","     ```"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"40ON8uUmTGn8"},"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))"]},{"cell_type":"markdown","metadata":{"vscode":{"languageId":"python"},"id":"XDkXr-0ITGn8"},"source":["\n","**Warning:** the following does not create a tuple, but a variable of type string!"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"8pyqIX6gTGn9"},"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))"]},{"cell_type":"markdown","metadata":{"id":"qWhke9XsTGn9"},"source":["* Since tuples can contain any type of objects, they can also contain lists or other tuples (or lists):"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"y4xgmH5ZTGn9","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687840525047,"user_tz":-420,"elapsed":317,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"e11dadd4-ec7e-4bd2-cc45-725c8ca7b707"},"outputs":[{"output_type":"stream","name":"stdout","text":["The content of the tuple is: ('a', 4.2, 5, [2, 'spam'])\n","The length of tuple is: 4\n","The last element of the tuple is: [2, 'spam']\n"]}],"source":["tuple_2 = ('a', 4.2, 5, [2, \"spam\"])\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!"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Qlsyxn9VTGn9"},"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])"]},{"cell_type":"markdown","metadata":{"id":"ZLcJj5RKTGn9"},"source":["#### Creating empty lists and tuples"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"2Q5WpkCQTGn9","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687840571765,"user_tz":-420,"elapsed":5,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"35ca68d0-efb9-45b3-b39f-ed4313497875"},"outputs":[{"output_type":"stream","name":"stdout","text":["Content: []  Type: <class 'list'>  Length: 0\n","Content: ()  Type: <class 'tuple'>  Length: 0\n"]}],"source":["list_1 = []\n","list_1 = list()\n","print(\"Content:\", list_1, \" Type:\", type(list_1), \" Length:\", len(list_1))\n","\n","tuple_1 = ()\n","tuple_1 = tuple()\n","print(\"Content:\", tuple_1, \" Type:\", type(tuple_1), \" Length:\", len(tuple_1))"]},{"cell_type":"markdown","metadata":{"id":"fnJtFUTATGn9"},"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."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"pJbeK1-OTGn-"},"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","print(tuple_1)"]},{"cell_type":"markdown","metadata":{"id":"zmdFc7M8TGn-"},"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`"]},{"cell_type":"markdown","metadata":{"id":"li0aJ-YzTGn-"},"source":["\n","[Back to ToC](#toc)\n","\n","### Accessing values: list and tuple slicing <a id='21'></a>\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","<img src=\"https://github.com/sib-swiss/first-steps-with-python-training/raw/master/notebooks/img/var_list1.png\" alt=\"representation of a list variable in memory with indices\" style=\"width:250px;\" />\n","\n","* As with strings, remember that the end position index is **excluded** from the slicing."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"rBVM_J64TGn-"},"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"]},{"cell_type":"markdown","metadata":{"id":"RQm9I3dHTGn-"},"source":["\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 <module>\n","          1 my_list = [1, 2, \"spam\"]\n","    ----> 2 my_list[3]\n","\n","    IndexError: list index out of range\n","```"]},{"cell_type":"markdown","metadata":{"id":"dagLpfwyTGn-"},"source":["\n","[Back to ToC](#toc)\n","\n","### When to use `list` or `tuple`? Mutability - an important difference between lists and tuples <a id='22'></a>\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","\n","<br>\n","\n","**Use tuples** when:\n","  * You need to store a sequence of objects that will not change in your program (fixed length).\n","  * You want to be sure that a sequence of objects will not be accidentally modified - a\n","    sort of **write-protection**.\n","  * Tuples are slightly more memory efficient than list.\n","      ```py\n","        import sys\n","        print(sys.getsizeof((1, 2, 3, 4, 5)))  # -> 80 bytes\n","        print(sys.getsizeof([1, 2, 3, 4, 5]))  # -> 96 bytes.\n","      ```\n","\n","<br>\n","\n","**Use lists** when:\n","  * You need to store a sequence of objects that will be modified over time.\n","  * You need to have a sequence that can be grown (add elements) or shrunk (remove elements).\n","\n","\n","For more details about object mutability in python, see the **Additional Theory** section at the end of this notebook.\n","\n","\n","**Example:** because lists are mutable, we can modify an element in a list (or add/remove an element from a list)."]},{"cell_type":"code","source":[],"metadata":{"id":"edFOAriC0x_Z"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["my_list = [1 , 2 , 3 , 5 , 5.2 , 6.99, True, 'A']\n","print(my_list[3])"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"R58vKEbjJ0ap","executionInfo":{"status":"ok","timestamp":1687840838170,"user_tz":-420,"elapsed":3,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"c4cb6118-4efc-435f-a710-6d11aa360a21"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["5\n"]}]},{"cell_type":"code","execution_count":null,"metadata":{"id":"d9uht1UGTGn_","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687840888862,"user_tz":-420,"elapsed":324,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"0f4b1a69-007c-440a-bb73-e993bbb14b83"},"outputs":[{"output_type":"stream","name":"stdout","text":["Position number 4 in list is : Spam , with data type <class 'str'>\n","The full list : [1, 2, 3, 'Spam', 5.2, 6.99, True, 'A']\n"]}],"source":["\n","\n","# We now modify the 4th element of the list:\n","my_list[3] = \"Spam\"\n","print('Position number 4 in list is :', my_list[3], ', with data type', type(my_list[3]))\n","print('The full list :', my_list)"]},{"cell_type":"markdown","metadata":{"scrolled":true,"vscode":{"languageId":"python"},"id":"-Zi7lZV6TGn_"},"source":["Trying to modify a tuple raises a **`TypeError`**:"]},{"cell_type":"code","execution_count":null,"metadata":{"scrolled":true,"id":"N-dt7U8ETGn_","colab":{"base_uri":"https://localhost:8080/","height":189},"executionInfo":{"status":"error","timestamp":1687840947008,"user_tz":-420,"elapsed":348,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"b31893db-4334-468f-ae7b-2e70258792d9"},"outputs":[{"output_type":"error","ename":"TypeError","evalue":"ignored","traceback":["\u001b[0;31m---------------------------------------------------------------------------\u001b[0m","\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)","\u001b[0;32m<ipython-input-42-a333d697b3a4>\u001b[0m in \u001b[0;36m<cell line: 2>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0mmy_tuple\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m \u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m \u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m \u001b[0;34m,\u001b[0m \u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mmy_tuple\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"spam\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m","\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment"]}],"source":["my_tuple = (1 , 2 , 3 , 5)\n","my_tuple[3] = \"spam\""]},{"cell_type":"markdown","metadata":{"id":"MeFvaN3kTGn_"},"source":["\n","What can be done however, is to **assign a new tuple to the same variable** - this will *look* like we have modified a tuple, but in fact we have created a new tuple object and assigned it to our variable."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"mrM-A-yMTGn_"},"outputs":[],"source":["my_tuple = (1 , 2 , 3 , 5)\n","print(my_tuple)\n","\n","my_tuple = (1 , 2 , 3 , \"spam\")  # We do not modify an existing tuple: we create a new one.\n","print(my_tuple)\n"]},{"cell_type":"markdown","metadata":{"id":"NB1GQ1XoTGn_"},"source":["<div class=\"alert alert-block alert-warning\">\n","\n","**Tips in Python**\n","    \n","</div>"]},{"cell_type":"markdown","metadata":{"id":"a4KyRF6eTGoA"},"source":["\n","### Copy of list content vs. copy of pointer (copying mutable values)\n","\n","When assigning a variable to another variable (as done below when assigning `l1` to `l2`), we are not duplicating the content of the existing variable: instead, we only create **a new pointer** to the content of the original variable."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"9HjcC4NITGoA"},"outputs":[],"source":["l1 = [1, 2, 3]\n","l2 = l1\n","print(\"The content of list 1:\", l1)\n","print(\"The content of list 2:\", l2)\n","\n","# By modifying the underlying list to which both l1 and l2 are pointing, both l1 and l2\n","# return the modified value.\n","l2[0] = -1\n","print(\"The content of list 1:\", l1)\n","print(\"The content of list 2:\", l2)\n","\n","print(\"\\nAre both list pointing to the same memory location?\", l1 is l2)\n","print(\"Memory locations of the 2 lists:\", id(l1), id(l2), sep=\"\\n\")"]},{"cell_type":"markdown","metadata":{"id":"diV5D7lYTGoA"},"source":["To make a copy of the actual list content, we must use the **`copy()`** method of list."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"hnETzO1xTGoA"},"outputs":[],"source":["l1 = [1, 2, 3]\n","l2 = l1.copy()\n","print(l1)\n","print(l2)\n","\n","# Now l1 and l2 are pointing to different memory locations.\n","l2[0] = -1\n","print('Lets check the difference')\n","print(l1)\n","print(l2)\n","\n","print(\"\\nAre both list pointing to the same memory location?\", l1 is l2)\n","print(\"Memory locations of the 2 lists:\", id(l1), id(l2), sep=\"\\n\")"]},{"cell_type":"markdown","metadata":{"id":"zHg1o3qMTGoA"},"source":["[Back to ToC](#toc)\n","\n","### Manipulating lists: adding and removing elements <a id='23'></a>\n","\n","Remember the `help()` function ? Let's use it to gain a better understanding of the lists :"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"T4VkcL-oTGoA"},"outputs":[],"source":["help(list)"]},{"cell_type":"markdown","metadata":{"id":"H8XG5U_8TGoA"},"source":["That's a lot of information... let's go through it!  \n","* First we learn that `list` is a class (i.e. a specific type of object).\n","  Calling `list()` can thus create instances (instantiate objects) of type `list`.\n","* The help page then tells us that lists are:\n","  \n","  > built-in mutable sequence\n","   \n","  and describes the behavior of `list()` if no argument is given (creates an empty list).\n","  <br>\n","  \n","* The help lists all methods available for class `list`, under `Methods defined here:`:\n","    * **Methods** are functions that can be called on objects of the class they belong to.\n","      This often enable some basic manipulation of objects of that type.  \n","    * Methods are called using the syntax **`object.method(...)`**.\n","    * Methods that start with **`__`** are **private methods**. They are not meant to be directly called\n","      by the end user.\n","      \n","      > *Note:* the double underscore **`__`** is called a **dunder**.\n","      \n","    * The **`/` symbol** found in some method signatures indicates that **all arguments present before the `/`\n","      are positional arguments, even if they have a default value**. They have to be passed in the correct\n","      order, and cannot be passed with their argument name, i.e. `argument_name=value` -\n","      [more details here](https://www.python.org/dev/peps/pep-0570).\n","    * The **`*` symbol** found in some method signatures indicates that **all arguments after the `*` are\n","      keyword arguments only**. In other words, no positional arguments are allowed after the `*`, and all\n","      arguments passer after the `*` must always be passed as `argument_name=value` -\n","      [more details here](https://peps.python.org/pep-3102)\n","\n","Let's focus on 3 methods of the `list` class:\n"," * **`append(self, object, /)`**: this method adds an object - given as argument - at the end of the list.\n"," * **`extend(self, iterable, /)`**: this method concatenates (extends) the list with the items from the iterable\n","    passed as argument.\n"," * **`insert(self, index, object, /)`**: this method inserts an object - given as the 2nd argument - before\n","   the index given as the 1st argument.\n","\n","<br>\n","\n","**Example 1:** appending a single element."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"YqsUCcd1TGoB"},"outputs":[],"source":["my_list = [1 , 2 , 5]\n","print(\"Initially, my list is:\\n\", my_list)\n","\n","# Calling the \"append()\" method of the \"my_list\" list to add an element at the end of it.\n","my_list.append(\"ham\")\n","print(\"The list, after appending 'ham' is now:\\n\", my_list)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"ojxlrrDQTGoB"},"outputs":[],"source":["my_list.append(\"eggs\")\n","print(my_list)"]},{"cell_type":"markdown","metadata":{"id":"iZW_XDltTGoB"},"source":["* Trying to add a string to a list with **`.extend()`** can lead to unexpected results."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"nQ13dZ6OTGoB"},"outputs":[],"source":["my_list.extend(\"eggs\")\n","print(my_list)"]},{"cell_type":"markdown","metadata":{"id":"bJWDNE5rTGoB"},"source":["* *Note:* to add a string with `.extend()`, it has to be an element of an iterable (list, tuple, etc)."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"tMDRgDoWTGoB"},"outputs":[],"source":["my_list = [1 , 2 , 3]\n","my_list.extend((\"eggs\",))\n","print(my_list)\n","my_list.extend([\"eggs again\"])\n","print(my_list)"]},{"cell_type":"markdown","metadata":{"id":"SbZ9bwBeTGoC"},"source":["**Example 2:** adding multiple values to a list - `append()` vs. `extend()` vs. concatenation.\n","* **`append(value)`** adds the specified value at the end of the list as a single value.\n","* When trying to add multiple values to a list, it might not have the desired effect."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"uxWbuWDzTGoC"},"outputs":[],"source":["my_list = [1, 2, 3]\n","my_list.append([\"spam\", \"eggs\"])\n","print(my_list)\n","print(\"List length:\", len(my_list), \"\\n\")"]},{"cell_type":"markdown","metadata":{"id":"EEf7n8mTTGoC"},"source":["* **`extend(iterable)`** add the values given in the specified **iterable** (e.g. a list, tuple, generator) to\n","  the list."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"irD6h1epTGoC"},"outputs":[],"source":["my_list = [1, 2, 3]\n","my_list.extend([\"spam\", \"eggs\"])\n","print(my_list)\n","print(\"List length:\", len(my_list), \"\\n\")"]},{"cell_type":"markdown","metadata":{"id":"xkW65n5RTGoC"},"source":["* **List concatenation** has the same effect as `extend()`."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"ye9vcDRJTGoC"},"outputs":[],"source":["my_list = [1, 2, 3]\n","my_list += [\"spam\", \"eggs\"]   # This is the same as: my_list = my_list + [\"spam\", \"eggs\"]\n","print(my_list)\n","print(\"List length:\", len(my_list), \"\\n\")"]},{"cell_type":"markdown","metadata":{"vscode":{"languageId":"python"},"id":"HcMCgQOgTGoC"},"source":["#### `insert()` method\n","\n","* Adding en element at a **specific position in the list** can be done with the **`insert()`** method.\n","* In this example, we add an element in second position of `my_list`.\n","* Remember that Python indices start with 0, so inserting before position 1 puts\n","  the new object in second position in `my_list` (and not in the first)."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"3f7zF4MbTGoD"},"outputs":[],"source":["my_list = [1, 2, 3]\n","my_list.insert(1 , \"beans\")\n","print(\"list after insert:\", my_list)"]},{"cell_type":"markdown","metadata":{"id":"Cw4bOmZVTGoD"},"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":{"id":"Oyv51VABTGoD"},"source":["### Deleting elements in a list\n","\n","* `list_object.pop(x)`: **deletes** the element at position `x` **and returns it**.\n","  If no arguments are passed to `pop()`, the last element of the list is removed by default.\n","* `del list_object[]`: **deletes** a single element or a slice.\n","\n","*Note:* using the `.pop()` method is generally considered to be more *pythonic* than using `del`.\n","\n","**Example:** deleting with `del`:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"g_uwDpZkTGoD"},"outputs":[],"source":["a_list = list(range(21))\n","print(\"Original list:\\n\", a_list, \"\\n\")\n","\n","# Delete the last element from the list.\n","del a_list[-1]\n","print(\"Deleted the last element:\\n\", a_list, \"\\n\")\n","\n","# Delete all elements in positions 0 to 9. The element in position 10 is not deleted.\n","del a_list[0:10]\n","print(\"Deleted elements 0-9:\\n\", a_list)"]},{"cell_type":"markdown","metadata":{"id":"TCSONaHZTGoD"},"source":["**Example:** deleting an item with the `pop()` method:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"0gI3w1wtTGoD"},"outputs":[],"source":["a_list = list(range(21))\n","print(\"Original list:\\n\", a_list, \"\\n\")\n","\n","# By default, the last element of the list is removed by pop().\n","removed = a_list.pop()\n","print(\"Removed the last element:\\n\", a_list)\n","print(\"The element removed by pop is:\", removed, end=\"\\n\\n\")\n","\n","# To remove an element at a specific index, the index value must be passed to the .pop() method:\n","removed = a_list.pop(0)\n","print(\"Removed the first element:\\n\", a_list)\n","print(\"The element removed by pop is:\", removed)"]},{"cell_type":"markdown","metadata":{"id":"49i8XydnTGoD"},"source":["[Back to ToC](#toc)\n","\n","### From list to string, and back again ... <a id='24'></a>\n","Since string variable are **iterables** (they are sequences of characters), they can be converted to lists using the `list()` function:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"-P_IqJI6TGoE"},"outputs":[],"source":["quote = \"Drop your panties Sir William, I cannot wait till lunchtime.\"\n","individual_chars = list(quote)\n","\n","print(individual_chars)"]},{"cell_type":"markdown","metadata":{"id":"uCt_cMiJTGoE"},"source":["As can be seen above, the default behavior is that **each letter of the string becomes an element in the list**.\n","\n","However, often we prefer to create a list that contains each word of the string. For this we use the **`split()`** method of string:\n","* The `split()` method is very useful when reading formatted text files.\n","* By default, it splits on white space (i.e. spaces, tabs, newlines).\n","* It accepts an optional `sep` argument that allows separation of fields using the specified character (look up `help(str.split)` for details)."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"sDyqD234TGoE"},"outputs":[],"source":["quote = \"Drop your panties Sir William, I cannot wait till lunchtime.\"\n","words = quote.split()\n","\n","print(words)"]},{"cell_type":"markdown","metadata":{"id":"f5c6zuL3TGoF"},"source":["**To convert a list to a string**, the **`join()`** method can be used - it can be seen as the inverse of `split()`.  \n","Somehow counter-intuitively, the `join()` method applies to strings, and takes a list as argument:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"em-xcXL9TGoF"},"outputs":[],"source":["# Here, the separator calls the join method which accepts the list \"my_list\" as argument.\n","quote = \" \".join(words)\n","print(quote)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"l7dynw7BTGoG"},"outputs":[],"source":["# One can use a more exotic separator - in fact, any string can be used as separator.\n","quote = \"_SEP_\".join(words)\n","print(quote)\n","\n","# TIP: use an empty separator to join characters into a string.\n","a_string = \"\".join(['to','ba','c','co','ni','st'])\n","print(a_string)\n","print(type(a_string))"]},{"cell_type":"markdown","metadata":{"id":"EKFTfuShTGoG"},"source":["**Tip**: lists can be concatenated with the `+` operator, extended with `+=` (addition assignment) and \"multiplied\" with `*`:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"KhJ51mu3TGoG"},"outputs":[],"source":["# Create a new list by appending two lists.\n","list_one = [ \"hello\" , 1159 ]\n","list_two = list_one + [10.1, \"45\", 7]\n","print(list_one)\n","print(list_two)\n","\n","# Extend a list with the += operator.\n","list_one += [\"spam\", \"eggs\"]\n","print(list_one)\n","\n","# As well as multiplication\n","menu = [\"spam\", \"eggs\"] * 3\n","print(menu)"]},{"cell_type":"markdown","metadata":{"id":"p8DkBBgqTGoG"},"source":["<div class=\"alert alert-block alert-success\">\n","\n","### Micro Exercise 5 <a id='25'></a>\n","* Create a list with all integers from 0 to 3 in it.\n","* Add two numbers at the end of the list.\n","* Use a slicing operation to select the fourth element in the list.\n","\n","* **If you have the time:**\n","    * What is the difference between `list.pop()` and `list.remove()`?  \n","      Try to find-out empirically using the list `[6, 5, 5, 4, 3, 2, 1]` and\n","      running `.pop(5)` and `.remove(5)` on the list.\n","    * Why does `print(my_list.append(\"something\"))` print \"None\"?\n","\n","<div>"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"s069jDNYTGoH"},"outputs":[],"source":[]},{"cell_type":"markdown","metadata":{"id":"q_d117oNTGoH"},"source":["<details>\n","    \n","<summary> <b>Hints</summary>    \n","\n","```python\n","my_list = [0, 1, 2, 3]\n","\n","# Add two numbers at the end of the list\n","my_list.extend([4, 5])\n","\n","# Select the fourth element in the list using slicing\n","fourth_element = my_list[3]\n","\n","print(\"My List:\", my_list)\n","print(\"Fourth Element:\", fourth_element)\n","```\n","    \n","</details>"]},{"cell_type":"markdown","metadata":{"id":"tLiszInNTGoH"},"source":["[Back to ToC](#toc)\n","\n","## Dictionaries <a id='26'></a>\n","Dictionaries, or `dict`, are containers that associate a **key** to a **value**, just like a real world dictionary associates a word to its definition.\n","* Dictionaries are instantiated with the `{key:value}` or `dict(key=value)` syntax.\n","\n","    ```python\n","    color_code = {'blue': 23, 'green': 45, 'red': 8}\n","    ```\n","  \n","* **Keys** must be unique in the dictionary, and must be an immutable object (typically a `str`).\n","* **Values** can appear as many time as desired in the dictionary.\n","* The `[]` operator is used to **select objects from the dictionary**, but **using their key** instead\n","  of their index. E.g. `color_code[0]` is not a valid syntax (and will raise a **`KeyError`**), unless\n","  there is a key value of `0` in the dict (which is not the case in our example).\n","  \n","    ```python\n","    color_code['blue']   # returns 23\n","    color_code['red']    # returns 8\n","    ```\n","* Dictionaries are **mutable** objects: `key:value` pairs can be added and removed, values can be modified."]},{"cell_type":"markdown","metadata":{"id":"zHOrrXvrTGoH"},"source":["**Example 1:** Create a new `dict` with 2 key/value pairs."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"HLxHqlcqTGoH"},"outputs":[],"source":["d = {\n","    \"fox\": \"orange and white animal\",\n","    \"penguin\": \"black and white animal\"\n","}\n","print(d)"]},{"cell_type":"markdown","metadata":{"id":"nFH0g1rLTGoH"},"source":["* Retrieve values associated with keys."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"IccVpwsJTGoI"},"outputs":[],"source":["print(d[\"fox\"])\n","\n","key_value = \"penguin\"\n","print(\"A\", key_value, \"is a\", d[key_value])"]},{"cell_type":"markdown","metadata":{"vscode":{"languageId":"python"},"id":"3kCv5CqwTGoI"},"source":["* Edit an entry in the dictionary: this is possible, because `dict` are mutable types."]},{"cell_type":"code","execution_count":null,"metadata":{"scrolled":true,"id":"YQYU3deRTGoI"},"outputs":[],"source":["d[\"penguin\"] = d[\"penguin\"] + \", lives in the antarctic\"\n","print(d[\"penguin\"])\n","\n","# We can also use the \"+=\" shortcut:\n","d[\"penguin\"] += \" - where it's cold\"\n","print(d[\"penguin\"])"]},{"cell_type":"markdown","metadata":{"id":"EpzeYD7yTGoI"},"source":["* Trying to access an element of the `dict` by index is not possible. It raises a **`KeyError`**, because\n","  python is trying to find the key `0` in the dictionary and it does not exist."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"zRU-cwtWTGoI"},"outputs":[],"source":["print(d[0])"]},{"cell_type":"markdown","metadata":{"vscode":{"languageId":"python"},"id":"OFa9yWjmTGoI"},"source":["**Example 2:** create an empty dictionary, then add values to it.\n","* To **add a value to a `dict`**, we simply specify a new key value."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"F-utboy6TGoI"},"outputs":[],"source":["student_age = dict()\n","student_age = {}\n","print(student_age)\n","\n","student_age[\"Anne\"] = 26    # Add a new key value pair.\n","print(student_age)\n","\n","student_age[\"Victor\"] = 31  # Add a new key value pair.\n","print(student_age)"]},{"cell_type":"markdown","metadata":{"vscode":{"languageId":"python"},"id":"85NTRmEpTGoJ"},"source":["* Create a dictionary and directly add values to it."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"g267APVATGoJ"},"outputs":[],"source":["student_age = {\n","    \"Anne\": 26 ,\n","    \"Victor\": 31,\n","}\n","# Alternatively:\n","student_age = dict(Anne=26, Victor=31)\n","\n","print(student_age)\n","print(\"The age of Anne is  :\", student_age[\"Anne\"])\n","print(\"The age of Victor is:\", student_age[\"Victor\"])"]},{"cell_type":"markdown","metadata":{"id":"2EUXQb7VTGoJ"},"source":["\n","* Adding additional **`key:value`** pairs to a dictionary, or modifying an existing key is as easy as:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"3XZtP00YTGoJ"},"outputs":[],"source":["# Add a new entry to the dictionary:\n","student_age[\"Eleonore\"] = 5\n","print(student_age)\n","\n","# Modify the value associated to a key:\n","student_age[\"Eleonore\"] = 25\n","print(student_age)"]},{"cell_type":"markdown","metadata":{"id":"Qxg9Z9tITGoJ"},"source":["We are not restricted to a particular type for keys, nor for values. We can e.g. make dict of lists or dict of dict.  \n","However:\n","* In practice, it's best to use dictionaries for storing homogenous values (i.e. you probably don't want\n","  to store unrelated things in different keys).\n","* Mutable values **cannot be used as keys**!"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"ReQlHWBVTGoJ"},"outputs":[],"source":["student_age[0] = \"zero\"                             # Key is an integer number.\n","student_age[\"group_1\"] = [23, 25, 28]               # Value is a list.\n","student_age[\"group_2\"] = {\"bob\": 26, \"alice\": 27}   # Value is a dict.\n","print(student_age)\n","print(\"Bob's age is:\", student_age[\"group_2\"][\"bob\"])"]},{"cell_type":"markdown","metadata":{"id":"w73AUQ65TGoK"},"source":["Mutable values cannot be used as keys!"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"rnBgpuAATGoK"},"outputs":[],"source":["student_age[[1,2]] = \"shrubbery\""]},{"cell_type":"markdown","metadata":{"id":"mn8wl3gBTGoK"},"source":["### Removing items from a dictionary\n","Removing an item from a dictionary is similar as deleting items from a list:\n"," * **`dict.pop(key)`**: deletes the specified `key` from the dictionary and returns its value.\n"," * **`del dict[key]`**: deletes the specified `key` (and its associated value) from the dictionary."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"qPI-9K_fTGoK"},"outputs":[],"source":["student_age = {\n","    \"Anne\": 26,\n","    \"Victor\": 31,\n","    \"Eleonore\": 25,\n","}\n","print('dictionary:', student_age)\n","\n","del student_age[\"Victor\"]\n","removed_value = student_age.pop(\"Anne\")\n","print('dictionary:', student_age)\n","\n","print(\"\\nThe value we removed with 'pop' is:\", removed_value)"]},{"cell_type":"markdown","metadata":{"id":"EHy8Km2nTGoK"},"source":["<div class=\"alert alert-block alert-danger\">\n","    \n","# Lets take a look for bioinformatics needs\n","    \n","</div>"]},{"cell_type":"markdown","metadata":{"id":"G1kZSR0pTGoK"},"source":["1. Count for GC Content and visualize the data"]},{"cell_type":"code","source":["import random\n","\n","sequence = ''.join(random.choice('ATGC') for _ in range(2500))\n","print(sequence)"],"metadata":{"id":"v9Ka3ADA0Gq1","executionInfo":{"status":"ok","timestamp":1687919039461,"user_tz":-420,"elapsed":6,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"54c7d6df-c56e-46de-d78f-7bc929add687","colab":{"base_uri":"https://localhost:8080/"}},"execution_count":1,"outputs":[{"output_type":"stream","name":"stdout","text":["TGGGCCAAAGGGGAGGTATTTTCCCTCGCGGCCGCCCCATCTGTTAAACACGCGTCTTACTATCGTTCAAGAAGATGGGGCAAGGGGTATGTCTAGATCATAGCTCTAAAGCCCTGACCAGGCTGTAGCTGGACACGTTTCAACATATACGCCGGAGGGACGCGAAGTCCTCTTTTGATAGGGATGGGTTATTCTTTCTATCTAGTGTATCGATAAGACTCCGCGGTAGAGCTCGGTCTGTGGGAGATTCAGGTGCCGCTGGACTGAAAGAAGTACAGTCACATCACATCCAATGCGGCGAGGGGAACACTTTTCATGGAAAGACAGGGACTTCGTCGGCACCCCTAAAATTAAATGCTTGGCTTTCTACTCCCGTACCTAACCACGGATGTTTTAAGAGCAACATAGTCGCGTGTGTCAATTGGTAAAGAAGCTCTTTAATAAGTCCGTACCAAGCATACTTCATATTGAAAGGGCTTGGGCTTCACAGGTAGAATTTGACCATCGGAGAGTGCCATCGTAAGTGTATCTAGCTCCTAACAAAACATATTCCGTTATGTCCATTCTATAGAAGATTTTGAATTTCTAGGCTCATCTCCGCCTGTGATCCTCAAGCCGTCTGAGCACATACAGAAGATCCCAAGGCCAACTACGCACTCACACCGAATGCTACCGCCTAAATAGCGATTTAGAAGAACGTGTTCTTCCAGCGTTATCACTAGGTCAAAGATTTCACAGAGCGATAACGCACCCATCTGAAGATCGTAGGCCCGCACAGGGCGCGTATTCCCCATCCTTATTTTTTGTATCCTCGCGAGTAGGGTGCCTTGAGGACCATTCGCGGAGGGTACCTTCGGTGTCGTGACATTTGCCTCACTGCCTCTACACCCTGCAGAAAGGGTAGGCGTGCGCCTATAGCAGGAAGGGCATTACAGCTACGAAAGTGCCAATTAATCAGGCAGATAATGTGTTTTAAAGCTTCATGGATGATACCAATTTCCCGAAGGCCGGCAATCTCATAAGAGACTACTGGTGGTGGGCATTAGCCCGTGGGGCCCTGTGTGCTACGGGGTAAAGGGGCGAAGTTGCTCATTAACCGACGTGTTGGTGCTTGGATTCACCAATCGTCACATGAAAGGTTCCGTGAGTAGGCAGTCGCTCCTGATATTCTCCGGTGTGCTCTACCCTGTTACAATTTCTGGATGGACTGGAGAGACTCTAGGCCCCCTAGACGCAGATTGTGCGAGTGGCTCAATTAACGACGGTCGCGTAACAGCGAGACGCGTTGGCGTAAAAAGTAGTAGGTTAGTAACGGGAGCAGGTCGATGCGGGACTGACAAGAATAACGCGTCGGCCATTTCTAAACAAGACCCTAATATTACTGCTATGGGTCGCAATTTTTGCCAGGTATCGACGTTCCGATCTCAAGCCAAATGGTTGGTGAGGCAAAACAGCTTCACGAAGGCTGAGTTGGTGTCGTTTATTCTTCTAGTGGCCGCGGCTGACCGCGACTCTCGCATCCTCTTTAGGTGGATCATAGTGCGGCGTCAACTGCAGCGGCCCCAAATCAATTATCTTACTCACGGCTCGCCCAGGGCACTGTACTCCCACAAGTGTAGTCGGTTATAAGGTATTAGGCTAACTTCGGAGCGACAAGCTCGCTCACTCGGGCTCATACAAGTCCTTCGCCGTGAGAGACTCTTCTATTAGCTGGCTATTGACGGCCGACTGGAGCTAACTTTCCAACGCACCCTGATCCTTAACGCTCTCGCTAGACATCCCACTCGGAGCCTCTCTTCCGTACATTTAAGCACCATGGGTCGCCGAGAATCTTCAGAATAGGTCGTGCAGGTCCCTCACGGACTGGTATGACTGTGAGTCAGCGGCCCGTCTATCGGGAGTGCGGTGCTGAGATGAATGTCGGTCTTCAAGGCATGTCGACTCAGAGGGTTGTTGACAAGTGATCCCGATTTGAATCTCATGCAAACGCGGTCAAATAGAGCCTAAAAACGTTGGGGGGCTCGCCACCTTTCCAATCACACGTCCTGCTAGAATGACATCAGAACGTATCTATTGTAGGATCTAGATGCCCAGGGTCTGCCAGGGGAGCTGAATGATTCTGACTCTATTTGAGGTTGTGGATTAGCCCCTAGCCCTGGGTATTCCGATACGATTGCGGTAATGGAATTCTGGCGAGAAATCGGGCGCCTTACCTGTATTTTGGATGTAAGGGCATATCTTCAGGCACCATTCCGATATCGCTCCAAAAAGCAACAGGTGAGTCGGAGAAGTGATTTCTAGGTCTAACGTTTCAGCCGAATGAGTTCGTGCCACGGGGCTGTTCGCTTATATACAGCACCCAAGTGAACCATCCAGTTGTCTTCCCTACTTACATGTTGCCATCCCGGGGACGGTGTGCCACCTCCGAGGGACGGCATTCGCGGCACGCTGAGTTTTTGGGCACTGCACTCCTTACTTGCGTTGCATGAACGTTGTCACC\n"]}]},{"cell_type":"code","execution_count":null,"metadata":{"id":"88_ABSTNTGoK","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1687839948263,"user_tz":-420,"elapsed":4,"user":{"displayName":"Faris Izzatur Rahman","userId":"03185179294135315816"}},"outputId":"a254e520-e32a-4654-f921-b1b9a3df6058"},"outputs":[{"output_type":"stream","name":"stdout","text":["Sequence Length:  88\n","Total GC: 42.04545454545455\n"]}],"source":["sequence = \"ATGCTAGCTAGCTAGCTAGCTAGCTAGCTAGGGTTACACTCATATACCTTTCTACTATCTCATCAAATCGATGGCTAGCTACTAGCTA\"\n","print(\"Sequence Length: \", len(sequence))\n","\n","gc = ((sequence.count('G') + sequence.count('C')) / len(sequence)) * 100\n","print('Total GC:', gc)"]},{"cell_type":"markdown","metadata":{"id":"uUA1re4HTGoP"},"source":["<details>\n","\n","<summary> <b>Hints</summary>\n","\n","You can use len() to count total length, and count() for counting each char:\n","```python\n","sequence = \"ATGCGATCGATCGTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTAGCTA\"\n","print(\"Sequence Length: \", len(sequence))\n","gc_content = sequence.count('G') + sequence.count('C')\n","print(\"Total GC: \",gc_content)\n","```\n","</details>"]},{"cell_type":"markdown","metadata":{"id":"_jnPVAmETGoQ"},"source":["[Back to ToC](#toc)\n","\n","# Additional Theory <a id='28'></a>\n","-----------------------------\n","\n","\n","### Mutability of objects in Python <a id='29'></a>\n","\n","All objects in Python can be either **mutable** or **immutable**. This is an important notation that newcomers to Python need to be aware of, which otherwise can lead to serious bugs in our codes.\n","\n","What do we mean by *mutable*? We learnt earlier that **everything in Python is an object** and every variable holds an instance of an object. Once its type is set at runtime it can never change. A list is always a list, an integer is always an integer. However its value can be modified if it is mutable.\n","\n","A mutable object can be changed/modified after it is created, and an immutable object can’t."]},{"cell_type":"markdown","metadata":{"id":"NEJnX8HhTGoQ"},"source":["| Class   | Mutable |\n","| ------- |:-------:|\n","| `bool`  | no |\n","| `int`   | no |\n","| `float` | no |\n","| `str`   | no |\n","| `list`  | yes |\n","| `tuple` | no |\n","| `dict`  | yes |"]},{"cell_type":"markdown","metadata":{"id":"aewGuNgiTGoQ"},"source":["Mutability has not much practical importance for simple types, but it has for container types.  \n","Let's see this with some examples:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"aX5V3ALOTGoQ"},"outputs":[],"source":["a_str = \"Python\"\n","a_list = [\"P\", \"y\", \"t\", \"h\", \"o\", \"n\"]\n","a_tuple = (\"P\", \"y\", \"t\", \"h\", \"o\", \"n\")\n","a_dict = {0: \"P\", 1: \"y\", 2: \"t\", 3: \"h\", 4: \"o\", 5: \"n\"}"]},{"cell_type":"markdown","metadata":{"id":"1P8JOn0pTGoQ"},"source":["Let's try to modify an element (an individual char) in a string: it raises a **`TypeError`** because a string in an immutable type."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Zd2qti7hTGoR"},"outputs":[],"source":["# Let's try to change \"P\" into \"p\"\n","print(a_str[0])\n","a_str[0] = \"p\""]},{"cell_type":"markdown","metadata":{"vscode":{"languageId":"python"},"id":"UcuSuSquTGoR"},"source":["Let's try to modify an element in a list: this is possible, because a list is a mutable type."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"HFAqt5HOTGoS"},"outputs":[],"source":["print(a_list)\n","a_list[0] = \"p\"\n","print(a_list)"]},{"cell_type":"markdown","metadata":{"vscode":{"languageId":"python"},"id":"Wepn82ROTGoS"},"source":["However, the *immutable* cousin of list, the tuple, does not allow assignment:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Rya0_JOMTGoS"},"outputs":[],"source":["print(a_tuple[0])\n","a_tuple[0] = \"p\""]},{"cell_type":"markdown","metadata":{"id":"wyd5cF5jTGoS"},"source":["<br>\n","\n","Dictionaries are mutable, their values can be modified:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"c0ZF8kmDTGoT"},"outputs":[],"source":["print(a_dict)\n","a_dict[0] = \"p\"\n","print(a_dict)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"9ISF8LMATGoT"},"outputs":[],"source":["my_dict = {\"str\": a_str, \"list\": a_list}\n","another_dict = my_dict\n","print(another_dict[\"list\"])"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"uboK6YmPTGoT"},"outputs":[],"source":["# Now let's modify my_dict\n","my_dict[\"list\"][0] = \"P\"\n","# and see what happens to both dictionaries\n","print(\"my_dict:\", my_dict)\n","print(\"another_dict:\", another_dict)"]},{"cell_type":"markdown","metadata":{"id":"MF7hBwK4TGoT"},"source":["Although we never changed/modified `another_dict`, it was also changed. This is because the key **'list'** in both dictionaries refer to the same `list` object: `a_list`. It is mutable and once it is modified, both dictionaries will reflect this modification. Let's visit this with a final example."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"HhtY3BehTGoT"},"outputs":[],"source":["a_list[0] = \"Z\"\n","print(\"my_dict:\", my_dict)\n","print(\"another_dict:\", another_dict)"]},{"cell_type":"markdown","metadata":{"id":"TYR2dgZ6TGoT"},"source":["**To summarize:**\n","\n","* An object in Python can either be mutable or immutable.\n","* We can simply check it by trying to modify a variable.\n","* `str` and `tuple` are immutable\n","* `list` and `dict` are mutable\n","* We need to pay attention when we modify mutable objects that are referred from multiple variables!"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"P09d03-0TGoU"},"outputs":[],"source":["my_dict[\"str\"] = \"Zython\"\n","print(\"my_dict:\", my_dict)\n","print(\"another_dict:\", another_dict)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"hmpXvwiOTGoU"},"outputs":[],"source":["a_third_dict = my_dict.copy()\n","my_dict[\"str\"] = \"Kython\"\n","my_dict[\"list\"][0] = \"K\"\n","print(\"my_dict:\", my_dict)\n","print(\"third_dict:\", a_third_dict)"]}],"metadata":{"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.9.7"},"colab":{"provenance":[]}},"nbformat":4,"nbformat_minor":0}