diff --git a/00_index.ipynb b/00_index.ipynb
index 3ff34ba..db6ddd7 100644
--- a/00_index.ipynb
+++ b/00_index.ipynb
@@ -7,6 +7,7 @@
"# Introduction\n",
"\n",
"- [Introduction to the tutorial](./00_intro.ipynb)\n",
+ "- [A quick tour of Python](./00_python_intro.ipynb)\n",
"\n",
"# Basic Tutorial\n",
"\n",
@@ -42,13 +43,6 @@
"\n",
"- [Parallelism and concurrency in Python](./14_threads.ipynb)\n"
]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
}
],
"metadata": {
diff --git a/00_python_intro.ipynb b/00_python_intro.ipynb
new file mode 100644
index 0000000..98195a5
--- /dev/null
+++ b/00_python_intro.ipynb
@@ -0,0 +1,1447 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# A Quick Tour of Python"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## Table of Contents\n",
+ " - [References](#References)\n",
+ " - [Introduction](#Introduction)\n",
+ " - [Python Basics for Absolute Beginners](#Python-Basics-for-Absolute-Beginners)\n",
+ " - [What is code?](#What-is-code?)\n",
+ " - [Python syntax basics](#Python-syntax-basics)\n",
+ " - [Indentation: Python's superpower](#Indentation:-Python's-superpower)\n",
+ " - [Comments: notes to yourself](#Comments:-notes-to-yourself)\n",
+ " - [Hello, World!](#Hello,-World!)\n",
+ " - [What is an expression?](#What-is-an-expression?)\n",
+ " - [What is a string?](#What-is-a-string?)\n",
+ " - [How Python executes this code](#How-Python-executes-this-code)\n",
+ " - [Basic datatypes and operations](#Basic-datatypes-and-operations)\n",
+ " - [Numbers](#Numbers)\n",
+ " - [Strings](#Strings)\n",
+ " - [The `type()` function](#The-type()-function)\n",
+ " - [Dynamic typing](#Dynamic-typing)\n",
+ " - [Conditional execution](#Conditional-execution)\n",
+ " - [Loops](#Loops)\n",
+ " - [The `for` loop](#The-for-loop)\n",
+ " - [The `while` loop](#The-while-loop)\n",
+ " - [Functions](#Functions)\n",
+ " - [Why functions?](#Why-functions?)\n",
+ " - [A first example](#A-first-example)\n",
+ " - [Parameters and Arguments](#Parameters-and-Arguments)\n",
+ " - [Defining a function](#Defining-a-function)\n",
+ " - [The function body](#The-function-body)\n",
+ " - [Calling a function](#Calling-a-function)\n",
+ " - [`return` vs `print`](#return-vs-print)\n",
+ " - [Type hints (optional but helpful)](#Type-hints-(optional-but-helpful))\n",
+ " - [Docstrings: special comments for functions](#Docstrings:-special-comments-for-functions)\n",
+ " - [Putting it all together: A complete example](#Putting-it-all-together:-A-complete-example)\n",
+ " - [What's next?](#What's-next?)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2",
+ "metadata": {},
+ "source": [
+ "## References\n",
+ "\n",
+ "From the official documentation:\n",
+ "* [Beginner's Guide to Python](https://wiki.python.org/moin/BeginnersGuide)\n",
+ "* [Python for New Programmers](https://wiki.python.org/moin/BeginnersGuide/NonProgrammers)\n",
+ "* [Python for Programmers](https://wiki.python.org/moin/BeginnersGuide/Programmers)\n",
+ "* [The Python Language Reference](https://docs.python.org/3/reference/index.html)\n",
+ "* [Python Programming FAQ](https://docs.python.org/3/faq/programming.html)\n",
+ "\n",
+ "Other:\n",
+ "* [Python For Everybody](https://www.py4e.com/lessons)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "## Introduction\n",
+ "\n",
+ "Welcome! 🐍\n",
+ "\n",
+ "This notebook provides a gentle introduction to the fundamental concepts of Python programming. \n",
+ "\n",
+ "Python is a high-level, interpreted programming language known for its clean syntax and readability.\n",
+ "In this tour, we will explore the core building blocks that make Python so popular.\n",
+ "\n",
+ "Each section introduces a concept with simple examples.\n",
+ "For deeper coverage of any topic, we provide links to the detailed notebooks that we will cover during the course of this training.\n",
+ "\n",
+ "Let's begin!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4",
+ "metadata": {},
+ "source": [
+ "## Python Basics for Absolute Beginners\n",
+ "\n",
+ "If you have never programmed before, welcome!\n",
+ "This section will help you understand the fundamental building blocks of Python code."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "### What is code?\n",
+ "\n",
+ "**Code** is simply a set of instructions that tells a computer what to do.\n",
+ "When you write Python code, you are writing instructions in a language that humans can read and computers can execute.\n",
+ "\n",
+ "Think of it like a recipe:\n",
+ "- A recipe has steps written in a human language\n",
+ "- Code has steps written in a programming language (Python, in our case)\n",
+ "- Just as a chef follows a recipe, the computer follows your code\n",
+ "\n",
+ "The computer reads your Python code and performs the actions you have specified, one instruction at a time."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6",
+ "metadata": {},
+ "source": [
+ "### Python syntax basics\n",
+ "\n",
+ "**Syntax** refers to the rules for how code must be written.\n",
+ "Just like any natural language, programming languages have syntax rules too.\n",
+ "\n",
+ "Here are some basic Python syntax rules:\n",
+ "\n",
+ "#### 1. Statements and lines\n",
+ "\n",
+ "Most Python code is written as **statements**, meaning individual instructions that do something.\n",
+ "Each statement is typically written on a new line:\n",
+ "\n",
+ "```python\n",
+ "x = 5\n",
+ "y = 10\n",
+ "z = x + y\n",
+ "```\n",
+ "\n",
+ "Each line above is a separate statement."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7",
+ "metadata": {},
+ "source": [
+ "#### 2. Variables\n",
+ "\n",
+ "You might have noticed that in the example above we used `x`, `y`, and `z`.\n",
+ "These are **variables**.\n",
+ "Variable names can use any alphanumeric character (letters and numbers) and underscore, but they **cannot** start with numbers.\n",
+ "\n",
+ "It is a good practice to choose variable names that describe what they are used for.\n",
+ "Try to avoid placeholders, or generic names such as `x`, `y`, `my_variable`, or `func`.\n",
+ "\n",
+ "Examples:\n",
+ "\n",
+ "- `gamma_factor` is **valid**\n",
+ "- `_planck_constant` is **valid**\n",
+ "- `epsilon_0` is **valid**\n",
+ "- `1_item` is **not** valid (because it starts with a number)\n",
+ "\n",
+ "A **variable** is like a label you can assign to an object.\n",
+ "Think of it as giving a name to a value so you can refer to it later.\n",
+ "\n",
+ "```python\n",
+ "x = 5 # Create a variable named 'x' and assign the number 5 to it\n",
+ "name = \"Alice\" # Create a variable named 'name' and assign the text \"Alice\" to it\n",
+ "```\n",
+ "\n",
+ "The `=` symbol is called the **assignment operator**.\n",
+ "Note that it does not mean \"equals\" like in math. \n",
+ "It means \"store the value on the right into the variable on the left.\"\n",
+ "\n",
+ "Variables are useful because they allow you to:\n",
+ "- **Reuse** the same value multiple times\n",
+ "- **Change** the value later if needed\n",
+ "- Make your code more **readable** (using `name` instead of just `Alice`)\n",
+ "\n",
+ "This \"assignment\" (binding names to objects) also happens with:\n",
+ "- Function definitions\n",
+ "- `import` statements\n",
+ "- Some language constructs (such as `for`, `while`, `with` , which all imply assignments)\n",
+ "\n",
+ "We do not have to go into detail here, but these are worth mentioning."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8",
+ "metadata": {},
+ "source": [
+ "#### 3. Case sensitivity\n",
+ "\n",
+ "Python is **case-sensitive**, which means it treats uppercase and lowercase letters as different:\n",
+ "\n",
+ "```python\n",
+ "name = \"Alice\" # This is different from...\n",
+ "Name = \"Alice\" # ...this variable\n",
+ "```\n",
+ "\n",
+ "Python understands the variables `name` and `Name` as completely different from each other."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9",
+ "metadata": {},
+ "source": [
+ "#### 4. Parentheses and function calls\n",
+ "\n",
+ "When you want to use a **function** (a pre-written piece of code that does something), you write its name followed by parentheses `()`:\n",
+ "\n",
+ "```python\n",
+ "print(\"Hello!\")\n",
+ "```\n",
+ "\n",
+ "If the function needs information to work with, you put that information inside the parentheses.\n",
+ "We call this information **arguments**.\n",
+ "\n",
+ "We are going to dive deeper into this topic, when we talk about [Functions](./00_python_intro.ipynb#Functions) later."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "10",
+ "metadata": {},
+ "source": [
+ "### Indentation: Python's superpower\n",
+ "\n",
+ "This is one of the most important concepts in Python: **indentation** refers to the spaces (or tabs) at the beginning of a line of code.\n",
+ "\n",
+ "In many programming languages, indentation is just for readability.\n",
+ "But in Python, **indentation has meaning**: it defines the structure of your code."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "11",
+ "metadata": {},
+ "source": [
+ "#### Why indentation matters\n",
+ "\n",
+ "Indentation tells Python which lines of code belong together as a **block**.\n",
+ "Let's see an example:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Correct indentation\n",
+ "if 10 > 5:\n",
+ " print(\"This line is indented\")\n",
+ " print(\"This line is also indented\")\n",
+ " print(\"All these lines belong to the 'if 10 > 5' block\")\n",
+ "\n",
+ "print(\"This line is NOT indented, so it's outside the 'if' block\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "13",
+ "metadata": {},
+ "source": [
+ "**What happened here?**\n",
+ "\n",
+ "1. The line `if 10 > 5:` ends with a colon `:` and this tells Python \"a block of code is coming next\"\n",
+ "2. The next three `print` statements are **indented** (they start with 4 spaces)\n",
+ "3. These indented lines form a **block** and they only run if the condition `10 > 5` is true\n",
+ "4. The last `print` statement is **not indented**, so it is outside the block and always runs\n",
+ "\n",
+ "Think of indentation like this:\n",
+ "```\n",
+ "Code at the left edge (no indent) → Always runs\n",
+ " Indented code → Runs only under certain conditions\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "14",
+ "metadata": {},
+ "source": [
+ "#### Common indentation mistakes\n",
+ "\n",
+ "Here are some errors beginners often make:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "15",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Missing indentation:\n",
+ "# This will cause an IndentationError!\n",
+ "\n",
+ "if 10 > 5:\n",
+ "print(\"This should be indented!\")\n",
+ "\n",
+ "# The line above would give an error because print is not indented"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "16",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Inconsistent indentation:\n",
+ "# This will also cause an IndentationError!\n",
+ "\n",
+ "if 10 > 5:\n",
+ " print(\"Indented with 4 spaces\")\n",
+ " print(\"Indented with 2 spaces - ERROR!\")\n",
+ "\n",
+ "# Python requires consistent indentation within the same block"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "17",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Inconsistent indentation:\n",
+ "# This will NOT cause an error but will lead to unexpected behavior!\n",
+ "\n",
+ "x = 15\n",
+ "\n",
+ "if x > 10:\n",
+ " print(\"x is greater than 10\")\n",
+ "print(\"This should only print if x > 10, but it always prints!\")\n",
+ "\n",
+ "# The second print is not indented, so it is outside the if block\n",
+ "# It will execute regardless of whether x > 10 is true or false"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "18",
+ "metadata": {},
+ "source": [
+ "
\n",
+ "
Indentation Tips
\n",
+ "
\n",
+ " - The Python standard is to use 4 spaces for each level of indentation.
\n",
+ " - Do not mix tabs and spaces, pick one and stick with it.
\n",
+ " - Most code editors (like Jupyter, VS Code) will automatically indent the code for you.
\n",
+ "
\n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "19",
+ "metadata": {},
+ "source": [
+ "### Comments: notes to yourself\n",
+ "\n",
+ "**Comments** are lines in your code that Python ignores.\n",
+ "They are notes for humans (including your future self) to understand what the code does.\n",
+ "\n",
+ "In Python, comments start with the `#` symbol.\n",
+ "Everything on the same line after the `#` symbol is ignored by Python."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "20",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# This is a comment - Python will ignore this line\n",
+ "\n",
+ "# Calculate the area of a rectangle\n",
+ "width = 10 # This comment explains what width represents\n",
+ "height = 5 # You can put comments at the end of lines too\n",
+ "area = width * height\n",
+ "\n",
+ "print(area) # Output: 50"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "21",
+ "metadata": {},
+ "source": [
+ "Comments are useful for:\n",
+ "- Explaining **why** you wrote the code a certain way\n",
+ "- Leaving notes for your future self or teammates\n",
+ "- Temporarily \"turning off\" code without deleting it\n",
+ "\n",
+ "\n",
+ "\n",
+ "
Good practice
\n",
+ " Write comments that explain the \"why,\" not the \"what.\"\n",
+ " Your code should be clear enough that it shows what it does; comments should explain why you made certain choices.\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "22",
+ "metadata": {},
+ "source": [
+ "## Hello, World!\n",
+ "\n",
+ "Let's start with the simplest possible Python program:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "23",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"Hello, world!\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "24",
+ "metadata": {},
+ "source": [
+ "This simple line already contains several important concepts.\n",
+ "Let's break them down."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "25",
+ "metadata": {},
+ "source": [
+ "### What is an expression?\n",
+ "\n",
+ "An **expression** is any piece of code that produces a value.\n",
+ "In the example above:\n",
+ "\n",
+ "- `\"Hello, world!\"` is an expression (it evaluates to the string value `\"Hello, world!\"`)\n",
+ "- `print(\"Hello, world!\")` is also an expression: It is a **function call** that evaluates to `None`, but produces the side effect of printing text\n",
+ "\n",
+ "Expressions are the building blocks of Python programs.\n",
+ "They can be as simple as a number (`42`) or as complex as any calculation (`(5 + 3) * 2`)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "26",
+ "metadata": {},
+ "source": [
+ "### What is a string?\n",
+ "\n",
+ "A **string** is a sequence of characters enclosed in quotes.\n",
+ "In Python, you can use either single quotes (`'`) or double quotes (`\"`):\n",
+ "\n",
+ "```python\n",
+ "\"Hello, world!\" # Double quotes\n",
+ "'Hello, world!' # Single quotes - equivalent\n",
+ "```\n",
+ "\n",
+ "Strings are one of Python's fundamental **data types**.\n",
+ "They represent text and are used extensively in programming."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "27",
+ "metadata": {},
+ "source": [
+ "### How Python executes this code\n",
+ "\n",
+ "Python is an **interpreted** language, which means that the Python interpreter reads and executes your code line by line, from top to bottom.\n",
+ "This interactive nature makes Python great for experimentation and learning.\n",
+ "\n",
+ "You can see this in action in Jupyter notebooks like this one: each cell is executed independently when you run it."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "28",
+ "metadata": {},
+ "source": [
+ "## Basic datatypes and operations\n",
+ "\n",
+ "Now let's explore some of Python's basic data types and what we can do with them."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "29",
+ "metadata": {},
+ "source": [
+ "### Numbers\n",
+ "\n",
+ "Python supports various numeric types.\n",
+ "Let's try some basic arithmetic:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "30",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "1 + 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "31",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "10 - 3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "32",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "4 * 5"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "33",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "15 / 3"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "34",
+ "metadata": {},
+ "source": [
+ "We can also make comparisons:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "35",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "3 > 5"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "36",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "3 < 5"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "37",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "3 == 5"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "38",
+ "metadata": {},
+ "source": [
+ "### Strings\n",
+ "\n",
+ "Strings can also be combined using the `+` operator (called **concatenation**):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "39",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "'Hello, ' + 'world!'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "40",
+ "metadata": {},
+ "source": [
+ "Notice how the `+` operator works differently depending on what you're adding.\n",
+ "Numbers are added mathematically, while strings are joined together.\n",
+ "This is a simple example of how Python adapts behavior based on data types."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "41",
+ "metadata": {},
+ "source": [
+ "### The `type()` function\n",
+ "\n",
+ "Python has a built-in function called `type()` that tells you what type of data you are working with:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "42",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "type(1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "43",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "type(1.0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "44",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "type(\"Hello\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "45",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "type(True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "46",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "type([1, 2, 3])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "47",
+ "metadata": {},
+ "source": [
+ "Here we see several fundamental types:\n",
+ "- `int` - integers (whole numbers)\n",
+ "- `float` - floating-point numbers (decimals)\n",
+ "- `str` - strings (text)\n",
+ "- `bool` - boolean values (`True` or `False`)\n",
+ "- `list` - ordered collections of items"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "48",
+ "metadata": {},
+ "source": [
+ "\n",
+ "
Note
\n",
+ " We will cover all topics related to datatypes very soon, during the
Basic Datatypes section of the tutorial.\n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "49",
+ "metadata": {},
+ "source": [
+ "### Dynamic typing\n",
+ "\n",
+ "An important characteristic of Python is that **type attribution is implicit and context-dependent**.\n",
+ "As you may have noticed, you do not need to explicitly declare the type of a variable, as you may have done in other programming languages.\n",
+ "Python figures it out automatically based on the value you assign."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "50",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x = 42\n",
+ "print(type(x))\n",
+ "\n",
+ "x = \"Now I'm a string!\"\n",
+ "print(type(x))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "51",
+ "metadata": {},
+ "source": [
+ "The variable `x` can change type freely. \n",
+ "This makes Python very flexible, but also means you need to be mindful of what type your variables hold."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "52",
+ "metadata": {},
+ "source": [
+ "## Conditional execution\n",
+ "\n",
+ "Programs often need to make decisions.\n",
+ "Python uses `if-else` statements to execute different code based on conditions:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "53",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if 5 > 3:\n",
+ " print(\"True\")\n",
+ "else:\n",
+ " print(\"False\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "54",
+ "metadata": {},
+ "source": [
+ "Since `5 > 3` evaluates to `True`, the block executes and prints \"True\". \n",
+ "\n",
+ "Let's try another example:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "55",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "temperature = 25\n",
+ "\n",
+ "if temperature > 30:\n",
+ " print(\"It's hot!\")\n",
+ "elif temperature > 20:\n",
+ " print(\"It's pleasant\")\n",
+ "else:\n",
+ " print(\"It's cold!\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "56",
+ "metadata": {},
+ "source": [
+ "Conditionals allow your program to **deviate** from linear execution and make decisions based on data."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "57",
+ "metadata": {},
+ "source": [
+ "## Loops\n",
+ "\n",
+ "Loops allow us to execute code repeatedly.\n",
+ "This is essential for processing collections of data or performing repetitive tasks."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "58",
+ "metadata": {},
+ "source": [
+ "### The `for` loop\n",
+ "\n",
+ "The most common type of loop in Python is the `for` loop, which iterates over a sequence:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "59",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for i in range(3):\n",
+ " print(i)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "60",
+ "metadata": {},
+ "source": [
+ "The `range(3)` function generates the sequence `[0, 1, 2]`, and the loop executes once for each value.\n",
+ "\n",
+ "Here's a practical example that sums the numbers in a list:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "61",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total = 0\n",
+ "\n",
+ "for num in range(5):\n",
+ " total = total + num\n",
+ "\n",
+ "print(total)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "62",
+ "metadata": {},
+ "source": [
+ "### The `while` loop\n",
+ "\n",
+ "The `while` loop continues executing as long as a condition remains `True`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "63",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "count = 0\n",
+ "\n",
+ "while count < 5:\n",
+ " print(count)\n",
+ " count = count + 1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "64",
+ "metadata": {},
+ "source": [
+ "Loops are fundamental for automating repetitive tasks and processing data collections.\n",
+ "\n",
+ "\n",
+ "
Note
\n",
+ " We will cover all topics related to Conditionals and Loops, during the
Control flow section of the tutorial.\n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "65",
+ "metadata": {},
+ "source": [
+ "## Functions\n",
+ "\n",
+ "As programs grow more complex, we need a way to organize and reuse code.\n",
+ "**Functions** are the solution to this."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "66",
+ "metadata": {},
+ "source": [
+ "### Why functions?\n",
+ "\n",
+ "Functions allow you to:\n",
+ "1. **Reuse code**: write once, use many times\n",
+ "2. **Organize code**: break complex problems into manageable pieces\n",
+ "3. **Abstract details**: hide complexity behind a simple interface"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "67",
+ "metadata": {},
+ "source": [
+ "### A first example\n",
+ "\n",
+ "Here's a simple function that greets someone:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "68",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def greet(name):\n",
+ " return \"Hello, \" + name + \"!\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "69",
+ "metadata": {},
+ "source": [
+ "Notice here how we are able not only to [concatenate strings](./00_python_intro.ipynb#Strings), as we have seen before, but also concatenate the value of variable `name` to the string, using the `+` sign.\n",
+ "\n",
+ "Now we can call this function with different names:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "70",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(greet(\"Alice\"))\n",
+ "print(greet(\"Bob\"))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "71",
+ "metadata": {},
+ "source": [
+ "\n",
+ "
Note
\n",
+ " We will explain every detail about functions in the
Functions notebook, but, for now, let's cover the basic information you will need in order to start the tutorial.\n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "72",
+ "metadata": {},
+ "source": [
+ "### Parameters and Arguments\n",
+ "\n",
+ "You can see that the function we defined above is expecting to receive a value for the variable called `name`.\n",
+ "The variable `name` itself is called a **parameter**.\n",
+ "\n",
+ "The value that we assign to this parameter, for example, `\"Alice\"`, is called an **argument**.\n",
+ "\n",
+ "These two terms are often used interchangeably, so no need to stress about that now.\n",
+ "Just remember that when we want to *define* and *call* a function, you need to do the following:"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "73",
+ "metadata": {},
+ "source": [
+ "### Defining a function\n",
+ "\n",
+ "To define a function you need to use the keyword `def`, followed by the name of the function.\n",
+ "The function name should not contain any space characters and, as a good practice, should be indicative of what the function is supposed to be doing.\n",
+ "\n",
+ "After that, you define the **parameters** of the function, inside **parentheses**.\n",
+ "You can have as many parameters as you want, separated by **commas**.\n",
+ "\n",
+ "Finally, remember what we mentioned about [indentation](./00_python_intro.ipynb#Indentation:-Python's-superpower) earlier:\n",
+ "The function **signature** finishes with a **colon** character.\n",
+ "Below that, all the code that you would like to include in your function, should be **indented**.\n",
+ "\n",
+ "Here is what we have so far:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "74",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def add_numbers(a, b):\n",
+ " # Does something..."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "75",
+ "metadata": {},
+ "source": [
+ "If you try to execute this cell, you will get an error.\n",
+ "That is because Python sees this function definition as incomplete.\n",
+ "Each function should have a **body** *and/or* a **return statement**."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "76",
+ "metadata": {},
+ "source": [
+ "### The function body\n",
+ "\n",
+ "The **body** of a function is the block of **indented code** that runs when the function is called.\n",
+ "It contains the instructions that perform the function's task."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "77",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def add_numbers(a, b): # 'a' and 'b' are PARAMETERS\n",
+ " # This is the body of the function\n",
+ " c = a + b\n",
+ " return c\n",
+ "\n",
+ "result = add_numbers(5, 3) # 5 and 3 are ARGUMENTS\n",
+ "print(result)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "78",
+ "metadata": {},
+ "source": [
+ "### Calling a function\n",
+ "\n",
+ "Calling a function is easy.\n",
+ "You write the name of the function and then, inside the parentheses, the arguments that you would like to pass, separated by commas.\n",
+ "\n",
+ "If your function is returning something, you can assign that value to a variable, similarly to how you would write any other [statement](./00_python_intro.ipynb#Python-syntax-basics).\n",
+ "We already did this in the example above:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "79",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result = add_numbers(5, 3)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "80",
+ "metadata": {},
+ "source": [
+ "This way you can reuse the value of `result` in other calculations.\n",
+ "\n",
+ "If your only objective is to print the result of the function and not reuse it in any way, then you could even pass the function call directly as the `print` argument:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "81",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(add_numbers(5, 3))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "82",
+ "metadata": {},
+ "source": [
+ "By now, you may have noticed that we have already used a function multiple times in our examples.\n",
+ "That function is no other than the `print` function.\n",
+ "\n",
+ "Notice how we call it like we would call any other function: \n",
+ "with its name, followed by parentheses, and inside the parentheses the argument."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "83",
+ "metadata": {},
+ "source": [
+ "### `return` vs `print`\n",
+ "\n",
+ "The code that we just wrote contains a crucial distinction that could confuse many beginners:\n",
+ "\n",
+ "- **`return`** sends a value back to whoever called the function (the value can be used in further calculations)\n",
+ "- **`print`** displays text on the screen (it's just for showing output to humans)\n",
+ "\n",
+ "Let's see the difference:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "84",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Function that PRINTS (does not return a value)\n",
+ "def add_numbers_and_print(a, b):\n",
+ " c = a + b\n",
+ " print(c)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "85",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Function that RETURNS a value\n",
+ "def add_numbers_and_return(a, b):\n",
+ " c = a + b\n",
+ " return c"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "86",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result1 = add_numbers_and_print(5, 3)\n",
+ "print(result1)\n",
+ "# result1 is None: no value was returned\n",
+ "\n",
+ "result2 = add_numbers_and_return(5, 3)\n",
+ "print(result2) \n",
+ "# result2 contains calculated value"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "87",
+ "metadata": {},
+ "source": [
+ "Here's why `return` is important:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "88",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def square(x):\n",
+ " result = x * x\n",
+ " return result\n",
+ "\n",
+ "# You can reuse the returned value\n",
+ "result = square(5)\n",
+ "print(result)\n",
+ "\n",
+ "# You can do further calculations\n",
+ "doubled = result * 2\n",
+ "print(doubled)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "89",
+ "metadata": {},
+ "source": [
+ "Notice that return is not followed by parentheses, as it is not a function."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "90",
+ "metadata": {},
+ "source": [
+ "\n",
+ "
Common Beginner Mistake
\n",
+ "
Beginners often use print in functions when they should use return. Remember:
\n",
+ "
\n",
+ " - If you want to see something → use
print \n",
+ " - If you want to use the value in your program → use
return \n",
+ " - You can do both! A function can print AND return
\n",
+ "
\n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "91",
+ "metadata": {},
+ "source": [
+ "### Type hints (optional but helpful)\n",
+ "\n",
+ "While Python does not require you to specify types, you can add **type hints** to make your code clearer.\n",
+ "Type hints document what types of data a function expects and returns.\n",
+ "\n",
+ "This is what the syntax looks like:\n",
+ "- `parameter: type` → tells what type the parameter should be\n",
+ "- `-> type` → tells what type the function returns\n",
+ "\n",
+ "For example:\n",
+ "\n",
+ "```python\n",
+ "# Without type hints\n",
+ "def multiply(a, b):\n",
+ " return a * b\n",
+ "\n",
+ "# With type hints\n",
+ "def multiply_with_hints(a: int, b: int) -> int:\n",
+ " return a * b\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "92",
+ "metadata": {},
+ "source": [
+ "\n",
+ "
Note
\n",
+ "
Type hints in Python are documentation, not enforcement. This means that Python will not stop you from passing the wrong type of argument when calling a function.
\n",
+ "
\n",
+ "\n",
+ "As mentioned above, type hints are optional.\n",
+ "However, throughout the tutorial, you will see that we use them extensively, especially in the exercises that we ask you to solve.\n",
+ "This is done mainly to provide you with additional information about what your code is expected to be doing."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "93",
+ "metadata": {},
+ "source": [
+ "### Docstrings: special comments for functions\n",
+ "\n",
+ "While regular comments use `#`, Python has a special type of comment called a **docstring** (short for \"documentation string\").\n",
+ "Docstrings are used to document what functions, classes, and modules do.\n",
+ "So let's see how we can use that in a function.\n",
+ "\n",
+ "Unlike regular comments, docstrings:\n",
+ "- Use **triple quotes** (`\"\"\"` or `'''`)\n",
+ "- Appear as the **first statement** inside a function\n",
+ "- Can span over multiple lines\n",
+ "- Bonus: they can be accessed programmatically (Python can read them!)\n",
+ "\n",
+ "Here's how they work:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "94",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def greet():\n",
+ " \"\"\"\n",
+ " This is a docstring.\n",
+ " It describes what the function does.\n",
+ " \n",
+ " You can write multiple lines to explain the function clearly.\n",
+ " \"\"\"\n",
+ " return \"Hello, world!\"\n",
+ "\n",
+ "# The function still works normally\n",
+ "print(greet())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "95",
+ "metadata": {},
+ "source": [
+ "A well-written docstring typically includes:\n",
+ "1. What the function does\n",
+ "2. What parameters it expects\n",
+ "3. What it returns\n",
+ "\n",
+ "Here is a more detailed example.\n",
+ "The exercises that you will be asked to solve will look like this:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "96",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def calculate_area(width, height):\n",
+ " \"\"\"\n",
+ " Calculate the area of a rectangle.\n",
+ " \n",
+ " Parameters:\n",
+ " width (float): The width of the rectangle\n",
+ " height (float): The height of the rectangle\n",
+ " \n",
+ " Returns:\n",
+ " float: The area of the rectangle (width × height)\n",
+ " \"\"\"\n",
+ " return width * height\n",
+ "\n",
+ "print(calculate_area(5, 10))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "97",
+ "metadata": {},
+ "source": [
+ "## Putting it all together: A complete example\n",
+ "\n",
+ "Let's create an example that covers all the concepts we have talked about:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "98",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def rectangle_area(width: float, height: float) -> float:\n",
+ " \"\"\"\n",
+ " Calculate the area of a rectangle.\n",
+ " \n",
+ " Parameters:\n",
+ " width: The width of the rectangle (in any unit)\n",
+ " height: The height of the rectangle (in same unit as width)\n",
+ " \n",
+ " Returns:\n",
+ " The area of the rectangle (width × height)\n",
+ " \"\"\"\n",
+ " # Function body starts here (indented)\n",
+ " area = width * height # Do the calculation\n",
+ " return area # Return the result \n",
+ " # Function body ends here\n",
+ "\n",
+ "# Now use the function:\n",
+ "result = rectangle_area(5.0, 10.0)\n",
+ "print(result)\n",
+ "\n",
+ "# We can use the returned value in more calculations\n",
+ "double_area = result * 2\n",
+ "print(double_area)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "99",
+ "metadata": {},
+ "source": [
+ "In this complete example:\n",
+ "\n",
+ "1. **`width` and `height`** are **parameters**\n",
+ "2. **`5.0` and `10.0`** are **arguments** (the actual values we pass when calling)\n",
+ "3. **Type hints** (`float` and `-> float`) document expected types\n",
+ "4. The **function body** (indented section) contains all the logic\n",
+ "5. **`print`** displays information for us to see\n",
+ "6. **`return`** gives back the calculated value so we can use it\n",
+ "7. The **docstring** (triple-quoted text) explains what the function does\n",
+ "\n",
+ "This is how all the pieces work together!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "100",
+ "metadata": {},
+ "source": [
+ "## What's next?\n",
+ "\n",
+ "Congratulations on completing this quick tour of Python! 🎉\n",
+ "\n",
+ "You have now learned the fundamental building blocks:\n",
+ "- ✅ Python syntax and indentation rules\n",
+ "- ✅ Comments and docstrings\n",
+ "- ✅ Basic data types and operations\n",
+ "- ✅ Conditional execution with `if-else`\n",
+ "- ✅ Loops with `for` and `while`\n",
+ "- ✅ Functions with parameters and return values\n",
+ "\n",
+ "Each topic we touched on has much more depth to explore in the detailed notebooks:\n",
+ "\n",
+ "- **[Basic datatypes](./01_basic_datatypes.ipynb)** - Dive deep into numbers, strings, lists, dictionaries, sets, and more\n",
+ "- **[Control flow](./02_control_flow.ipynb)** - Master conditionals, loops, and exception handling\n",
+ "- **[Functions](./03_functions.ipynb)** - Learn about parameters, scope, decorators, and functional programming\n",
+ "- **[Input/Output](./04_input_output.ipynb)** - Work with files, paths, and data persistence\n",
+ "- **[Object-oriented programming](./05_object_oriented_programming.ipynb)** - Explore inheritance, special methods, and design patterns\n",
+ "- **[Modules and packages](./06_modules_and_packages.ipynb)** - Organize code into reusable modules and work with external libraries\n",
+ "\n",
+ "Happy coding! 🐍"
+ ]
+ }
+ ],
+ "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.12.11"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}