{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "# 1: Basics" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This Python tutorial will cover the basics of\n", " - Jupyter Notebooks\n", " - basic types in Python\n", " - container types\n", " - control flow" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Jupyter\n", "\n", "A Jupyter Notebook consists of cells that can be executed. There are two fundamental different types of cells, markdown or code cells. The former renders the text as markdown while the latter runs the Python interpreter.\n", "\n", "Notebooks can be converted to Python scripts.\n", "\n", "Be aware that notebooks are stateful. E.g. executing a cell again is like adding this line two times in a script.\n", "\n", "Useful commands:\n", " - to run a cell and go to the next one, press Shift + Enter\n", " - to move from editing mode to navigation (move up and down in cells), press Esc\n", " - to enter editing mode from navigation, press Enter\n", " \n", "Let's start! Execute the lines below" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "jupyter": { "is_executing": true }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a = 0" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a = a + 1\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "If we rerun the cell above, `a` will have changed again! If you want to rerun everythin, restart the kernel first." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Notebooks offer convenient functionality, similar to IPython:\n", " - can use `!command` to execute bash\n", " - has tab-completion\n", " - prints automatically return value if it is not assigned to a variable\n", " - magic commands like %timeit\n", " \n", "We will use them later on more" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Basic types and operations\n", "\n", "Python has several basic types\n", " - numerical (float, int, complex)\n", " - string\n", " - bool\n", " \n", "There are several operations defined on them, as we have already seen in examples.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "jupyter": { "is_executing": true }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a = 1 # creates an integer\n", "\n", "b = 3.4 # float\n", "\n", "# several ways for strings\n", "c = \"hello\"\n", "d = 'world'\n", "cd = \"welcome to this 'world' here\" # we can now use '' inside (or vice versa)\n", "e = \"\"\"hello world\"\"\" # which we can also wrap\n", "e2 = \"\"\"hello\n", "world\n", "come here!\"\"\"\n", "\n", "g = True" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "jupyter": { "is_executing": true }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "type(a)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "With `type(...)`, we can determine the type of an object." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## strong typing\n", "\n", "Python is **strongly typed** (as opposed to weakly typed). This means that the type of the variable _matters_ and some interactions between certain types are not directly possible." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a = 1\n", "b = 2" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a + b" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "These are two integers. We are not surprised that this works. What about the following?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "mix_str_int = a + \"foo\"" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Maybe the following works?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "mix_str_int2 = a + \"5\"" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Python is strict on the types, but we can sometimes convert from one type to another, explicitly:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a + int(\"5\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "...which works because `int(\"5\") -> 5`.\n", "\n", "There are though some implicit conversions in Python, let's look at the following:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = 1.2\n", "print(type(f))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "int_plus_float = a + f\n", "print(type(int_plus_float))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This is one of the few examples, where Python automatically converts the integer type to a float. The above addition _actually_ reads as" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "int_plus_float = float(a) + f" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Similar with booleans as they are in principle 1 (`True`) and 0 (`False`)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "True + 5" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "For readability, it is usually better to write an explicit conversion." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Container types\n", "\n", "Python has several container types as also found in other languages. The most important ones are:\n", " - list (~array in other languages)\n", " - dict (~hash table in other languages)\n", " \n", "They can contain other objects which can then be assigned and accessed via the `[]` operator _(we will have a closer look at operators later on)_\n", "\n", "A list stores elements by indices, which are integers, while a dict stores elements by a `key`, which can be \"any basic type\" (to be precise: by their \"hash\", it can be any immutable type).\n", "\n", "Let's look at examples!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# creating a list\n", "list1 = [1, 2, 3]\n", "print(list1)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can access these element by indices, starting from 0" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "list1[0]" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can also assign a value to an place in the list" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "list1[1] = 42\n", "print(list1)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "and it can be extended with elements" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "list1.append(-5)\n", "print(list1)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Choosing a value that is not contained in the list raises an error. It is verbose, read and understand it.\n", "\n", "Being able to understand and interpret errors correctly is a key to becoming better in coding." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "list1[14]" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can play a similar game with dicts" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "person = {\n", " \"name\": \"Jonas Eschle\",\n", " \"age\": 42,\n", " 5: True,\n", " 11: \"hi\",\n", "} # we can use strings but also other elements\n", "print(person)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "print(person[\"name\"])\n", "print(person[5])\n", "print(person[11])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can also assign a new value to a key." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "person[\"age\"] = \"42.00001\"" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "... or even extend it by assigning to a key that did not yet exists in the dict" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "person[\"alias\"] = \"Mayou36\"\n", "print(person)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "As we see this works. Notice, that the dict has changed, same as the list before.\n", "\n", "Again, selecting a key that is not contained in the dict raises an error." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "person[\"nationality\"]" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "As any object in Python, there are many useful methods on `list` and `dict` that help you accomplish things. For example, what if we want to retrieve a value from a dict _only_ if the key is there and otherwise return a default value? We can use `get`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "hair_color = person.get(\n", " \"hair_color\", \"unknown color\"\n", ") # the second argument gets returned if key is not in dict\n", "print(hair_color)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Mutability\n", "\n", "Python has a fundamental distinction between mutable and immutable types.\n", "\n", "Mutable means, an object can be changed\n", "Immutable means, an object can not be changed\n", "\n", "As an example, `5` can not change; in general the basic types we looked at cannot change. We can change the value that is assigned to a variable, but the object `5` remains the same. The list and dicts we have seen above on the other hand are mutable, they have changed over the course of execution.\n", "\n", "Every mutable object has an immutable counterpart (but not vice-versa):\n", " - list -> tuple\n", " - dict -> frozendict\n", " - set -> frozenset\n", " - etc." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# creating a tuple\n", "tuple1 = (1, 3, 5)\n", "# or from a list\n", "tuple_from_list = tuple(list1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "list2 = [4, 5]\n", "tuple2 = (3, 4)\n", "list3 = list(tuple2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "While we can access the elements as we can for a list, we can neither _assign_ nor _append_ (or in generate _mutate_ the object:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "print(tuple1[1]) # access works!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "tuple1[0] = 5" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We will soon see the effects and needs for this..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## dynamic typing\n", "\n", "Python is dynamically typed (as opposed to statically typed). This means that a variable, which once was an int, such as `a`, can be assigned a value of another type." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a = 1" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a = \"one\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a = list1" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "... and so on" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Assignement and variables\n", "\n", "We've seen a few things up to now but have not really looked at the assignement and variables itself. Understanding Pythons variable is crucial to understand e.g. the following:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a = 5\n", "b = a\n", "print(a, b)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a = 3\n", "print(a, b)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "So far so good, no surprize here." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "list1 = [1, 3]\n", "list2 = list1\n", "print(list1, list2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "list2[0] = 99\n", "print(list1, list2)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "...but that was probably unexpected! Let's have a look at Pythons variable assignement." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Python variable assignement\n", "\n", "Assigning something to a variable in Python makes a name point to an actual object, so the name is only a reference. For example creating the variable `a` and assigning it the object `5` looks like this:\n", "![assignements1](figs/python_references1.jpg)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a = 3\n", "list_a = [1, 2]" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "![reference2](figs/python_references2.jpg)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "b = a # this assigns the reference of a to b\n", "list_b = list_a" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Both objects, `b` and `list_b` point now to the same objects in memory as `a` and `list_a` respectively. Re-assigning a variable let's it point to a different object\n", "![reference3](figs/python_references3.jpg)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a = \"spam\"\n", "list_a = [1, 5, 2, \"world\", 1]\n", "print(a, b)\n", "print(list_a, list_b)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Let's make them point to the same object again:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "b = a\n", "list_b = list_a\n", "print(a, b)\n", "print(list_a, list_b)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "list_a[1] = \"hello\"\n", "print(list_a, list_b)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Now we understand what happend: the object that both variables are pointing to simply changed. This is impossible with immutable objects (such as `3`), since they are immutable.\n", "\n", "Mutable objects usually offer the ability to create a copy." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "list_c = list_a.copy() # now there are two identical lists in the memory" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "list_a[2] = \"my\"\n", "print(list_a)\n", "print(list_b)\n", "print(list_c)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "`list_a` and `list_b`, pointing to the same object that was mutated, have changed, while `list_c`, pointing to a different object, remained the same.\n", "\n", "Let's have a look at two operators: the \"trivial\" `==` and the `is`:\n", "we know `==` pretty well, it tells whether the left and the right side are the same. More specific, it tells whether both sides have/represent the same _value_, not whether they are in fact the same object!\n", "The operator `is` tells us, whether two objects _are_ the same object (compare our assignement model above!)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "print(list_a == list_c) # not the same\n", "print(list_a == list_b) # the same" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "list_c[2] = \"my\" # make it the same as the other lists\n", "print(list_a == list_c)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "But, as we learned before, they are _not the same objects_!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "print(list_a is list_c) # nope!\n", "print(list_a is list_b) # yes!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Normally, we are only interested to compare the values, using `==`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "1 is None" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Sugar: comprehensions\n", "\n", "(taken from advanced Python lecture)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**List comprehensions**" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "N = 10\n", "\n", "list_of_squares = [i**2 for i in range(N)]\n", "sum_of_squares = sum(list_of_squares)\n", "\n", "print(\"Sum of squares for\", N, \"is\", sum_of_squares)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# [obj_to_return if ... else ... for i in ... for j in ... if ...]\n", "[i for i in range(10) if i % 2]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Dictionary comprehensions**" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "jupyter": { "is_executing": true }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "squares = {i: i**2 for i in range(10)}\n", "print(squares)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "N = 5\n", "print(\"The square of\", N, \"is\", squares[N])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Sugar: using Markdown" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Write comments inline about your code:\n", "\n", "Use LaTeX:\n", "\n", "$A = \\frac{1}{B+C}$\n", "\n", "Show lists:\n", "\n", "* A wonderful\n", "* List\n", "* This is\n", "\n", "Show code with syntax highlighting:\n", "\n", "**Python:** (but in a sad grey world)\n", "\n", "```\n", "print('Hello world')\n", "```\n", "\n", "**Python:**\n", "\n", "```python\n", "print('Hello world')\n", "```\n", "\n", "**C++:**\n", "\n", "```cpp\n", "#include \n", "\n", "std::cout << \"Hello world\" << std::endl;\n", "```\n", "\n", "**Bash:**\n", "\n", "```bash\n", "echo \"Hello world\"\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**f-strings**" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "pt_cut = 1789.234567890987654\n", "eta_low = 2\n", "eta_high = 5\n", "\n", "cut_string = f\"(PT > {pt_cut:.2f}) & ({eta_low} < ETA < {eta_high})\"\n", "print(cut_string)" ] } ], "metadata": { "celltoolbar": "Tags", "language_info": { "codemirror_mode": { "name": "ipython" }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python" }, "nbsphinx": { "execute": "auto" } }, "nbformat": 4, "nbformat_minor": 4 }