{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\"FMP\"\n", "\"AudioLabs\"\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\"B\"\n", "

Python Basics

\n", "
\n", "\n", "
\n", "\n", "

\n", "This notebook introduces some important aspects of the Python programming language. For more comprehensive tutorials, we refer to the following sources:\n", "\n", "

\n", "

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic Facts\n", "\n", "* Python is an interpreted (not compiled), open-source, multi-platform programming language.\n", "* There exist a set of modules for scientific computing (e.g. `numpy`, `scipy`, `matplotlib`, `librosa`) in Python.\n", "* Python uses indentation (and not brackets or `end`-commands) to separate blocks of code.\n", "* Comment lines start with the character `#`.\n", "* Useful functions for help:\n", " * Invoke the built-in help system: `help()` \n", " * List objects in namespace: `dir()`\n", " * Show global and local variables: `globals()`, `locals()`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data Types\n", "\n", "Let us start with some basic facts on Python variables:\n", "* Variables do not need to be declared; neither their type.\n", "* Variables are created automatically when they are first assigned.\n", "* A variable name may contain letters (`a`, `b`, ..., `Y`, `Z`) and the underscore (`_`).\n", "* Variable names are **case sensitive**.\n", "* All but the first character can also be positive integer numbers.\n", "* Usually one uses lower case letters and underscores to separate words.\n", "\n", "A string is given in single ticks (`'`) or double ticks (`\"`). If there is no other reason, we recommend single ticks. The following code assigns a string to a variable and prints it using the `print`-command." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.781820Z", "iopub.status.busy": "2024-02-15T09:01:51.781509Z", "iopub.status.idle": "2024-02-15T09:01:51.785727Z", "shell.execute_reply": "2024-02-15T09:01:51.784986Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Welcome to the Python Tutorial\n" ] } ], "source": [ "string_variable = 'Welcome to the Python Tutorial'\n", "print(string_variable)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here some basic string formatting:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.824473Z", "iopub.status.busy": "2024-02-15T09:01:51.824207Z", "iopub.status.idle": "2024-02-15T09:01:51.829307Z", "shell.execute_reply": "2024-02-15T09:01:51.828557Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is an integer: 17.\n", "This is string1: ABCD and this is string2: 1234.\n", "This is a floating point number: 03.142.\n" ] } ], "source": [ "print('This is an integer: %d.' % 17)\n", "print('This is string1: %s and this is string2: %6s.' % ('ABCD', '1234'))\n", "print('This is a floating point number: %06.3f.' % 3.14159265359)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Some basic math:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.832328Z", "iopub.status.busy": "2024-02-15T09:01:51.832080Z", "iopub.status.idle": "2024-02-15T09:01:51.836204Z", "shell.execute_reply": "2024-02-15T09:01:51.835424Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "n + 1 = 4\n", "n - 1 = 2\n", "n * 2 = 6\n", "n / 2 = 1.5\n", "n ^ 2 = 9\n" ] } ], "source": [ "n = 3\n", "print('n + 1 =', n + 1)\n", "print('n - 1 =', n - 1)\n", "print('n * 2 =', n * 2)\n", "print('n / 2 =', n / 2)\n", "print('n ^ 2 =', n ** 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Division always results in a floating point number, even if the number is divisible without remainder. (Note that there are differences between **Python 2** and **Python 3** in using `/`). If the result should be an integer (e.g., when using it as an index), one may use the `//` operator. The `%` yields the remainder." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.839270Z", "iopub.status.busy": "2024-02-15T09:01:51.839016Z", "iopub.status.idle": "2024-02-15T09:01:51.843000Z", "shell.execute_reply": "2024-02-15T09:01:51.842329Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Normal division: 4.0\n", "Integer division: 4\n", "Normal division: 1.6\n", "Integer division: 1\n", "Remainder of integer division: 3\n" ] } ], "source": [ "n = 8\n", "print('Normal division:', n / 2)\n", "print('Integer division:', n // 2)\n", "print('Normal division:', n / 5)\n", "print('Integer division:', n // 5)\n", "print('Remainder of integer division:', n % 5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For re-assigning a variable, one may use the following conventions:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.845964Z", "iopub.status.busy": "2024-02-15T09:01:51.845697Z", "iopub.status.idle": "2024-02-15T09:01:51.849370Z", "shell.execute_reply": "2024-02-15T09:01:51.848727Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "18\n", "36\n", "2.0\n", "1.4142135623730951\n" ] } ], "source": [ "n = 7\n", "n += 11\n", "print(n)\n", "\n", "n *= 2\n", "print(n)\n", "\n", "n /= 18\n", "print(n)\n", "\n", "n **= 0.5\n", "print(n)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The basic compound data types in Python are **lists** and **tuples**. A list is enclosed in square brackets and a tuple is enclosed in round brackets. Both are indexed with square brackets (with indexing starting with $0$). The `len` function gives the length of a tuple or a list." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.852396Z", "iopub.status.busy": "2024-02-15T09:01:51.852152Z", "iopub.status.idle": "2024-02-15T09:01:51.856949Z", "shell.execute_reply": "2024-02-15T09:01:51.856330Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['I', 'am', 'a', 'list']\n", "('I', 'am', 'a', 'tuple')\n", "I am generated from a tuple and a list\n", "4\n", "4\n", "\n", "\n" ] } ], "source": [ "var_lis = ['I', 'am', 'a', 'list']\n", "var_tup = ('I', 'am', 'a', 'tuple')\n", "print(var_lis)\n", "print(var_tup)\n", "print(var_lis[0], var_tup[1], 'generated from', \n", " var_tup[2], var_tup[3], 'and', var_lis[2], var_lis[3])\n", "print(len(var_tup))\n", "print(len(var_lis))\n", "\n", "print(type(var_lis))\n", "print(type(var_tup))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What is the difference between a list and a tuple? Tuples are **immutable** objects (i.e., their state cannot be modified after they are created) and a bit more efficient. Lists are more flexible. Here are some examples for list operations:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.859800Z", "iopub.status.busy": "2024-02-15T09:01:51.859558Z", "iopub.status.idle": "2024-02-15T09:01:51.863178Z", "shell.execute_reply": "2024-02-15T09:01:51.862621Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[-1, 2, 3, 10, 'a', '12', [13, 14]]\n", "[13, 14]\n" ] } ], "source": [ "var_lis = [1, 2, 3]\n", "var_lis[0] = -1\n", "var_lis.append(10)\n", "var_lis = var_lis + ['a', '12', [13, 14]]\n", "print(var_lis)\n", "print(var_lis[-1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One can index a list with start, stop, and step values (`[start:end:step`). Note that, in Python, the last index value is `end-1`. Negative indices are possible with `-1` referring to the last index. When not specified, `start` refers to the first item, `end` to the last item, and `step` is set to $1$." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.865876Z", "iopub.status.busy": "2024-02-15T09:01:51.865674Z", "iopub.status.idle": "2024-02-15T09:01:51.869861Z", "shell.execute_reply": "2024-02-15T09:01:51.869314Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "var_lis[0:3] = [11, 12, 13]\n", "var_lis[1:3] = [12, 13]\n", "var_lis[-1] = 15\n", "var_lis[0:3:2] = [11, 13]\n", "var_lis[0::2] = [11, 13, 15]\n", "var_lis[::-1] = [15, 14, 13, 12, 11]\n" ] } ], "source": [ "var_lis = [11, 12, 13, 14, 15]\n", "print('var_lis[0:3] =', var_lis[0:3])\n", "print('var_lis[1:3] =', var_lis[1:3])\n", "print('var_lis[-1] =', var_lis[-1])\n", "print('var_lis[0:3:2] =', var_lis[0:4:2])\n", "print('var_lis[0::2] =', var_lis[0::2])\n", "print('var_lis[::-1] =', var_lis[::-1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following examples shows how the elements of a list or tuple can be assigned to variables (called **unpacking**):" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.872591Z", "iopub.status.busy": "2024-02-15T09:01:51.872346Z", "iopub.status.idle": "2024-02-15T09:01:51.875556Z", "shell.execute_reply": "2024-02-15T09:01:51.875060Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 2\n", "3 4\n" ] } ], "source": [ "var_lis = [1, 2]\n", "[a, b] = var_lis\n", "print(a, b)\n", "\n", "var_tup = (3, 4)\n", "[c, d] = var_tup\n", "print(c, d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Leaving out brackets, tuples are generated." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.878029Z", "iopub.status.busy": "2024-02-15T09:01:51.877847Z", "iopub.status.idle": "2024-02-15T09:01:51.880866Z", "shell.execute_reply": "2024-02-15T09:01:51.880348Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1, 2)\n", "1 2\n" ] } ], "source": [ "t = 1, 2\n", "print(t)\n", "\n", "a, b = t\n", "print(a, b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `range`-function can be used to specify a tuple or list of integers (without actually generating these numbers):" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.883147Z", "iopub.status.busy": "2024-02-15T09:01:51.882971Z", "iopub.status.idle": "2024-02-15T09:01:51.885694Z", "shell.execute_reply": "2024-02-15T09:01:51.885217Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "range(0, 9)\n", "range(1, 9, 2)\n" ] } ], "source": [ "print(range(9))\n", "print(range(1, 9, 2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A range can then be converted into a tuple or list as follows:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.888060Z", "iopub.status.busy": "2024-02-15T09:01:51.887881Z", "iopub.status.idle": "2024-02-15T09:01:51.890887Z", "shell.execute_reply": "2024-02-15T09:01:51.890403Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 2, 3, 4, 5, 6, 7, 8]\n", "(1, 3, 5, 7)\n", "[9, 8, 7, 6, 5, 4, 3, 2]\n" ] } ], "source": [ "print(list(range(9)))\n", "print(tuple(range(1, 9, 2)))\n", "print(list(range(9, 1, -1)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Boolean values in Python are `True` and `False`. Here are some examples for basic comparisons:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.893266Z", "iopub.status.busy": "2024-02-15T09:01:51.893026Z", "iopub.status.idle": "2024-02-15T09:01:51.896229Z", "shell.execute_reply": "2024-02-15T09:01:51.895607Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n", "True\n", "False\n", "True\n" ] } ], "source": [ "a = 1\n", "b = 2\n", "print(a < b)\n", "print(a <= b)\n", "print(a == b)\n", "print(a != b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `bool` function converts an arbitrary value into a boolean value. Here, are some examples:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.898564Z", "iopub.status.busy": "2024-02-15T09:01:51.898387Z", "iopub.status.idle": "2024-02-15T09:01:51.901629Z", "shell.execute_reply": "2024-02-15T09:01:51.901139Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n", "False\n", "True\n", "False\n", "False\n", "False\n", "True\n" ] } ], "source": [ "print(bool('a'))\n", "print(bool(''))\n", "print(bool(1))\n", "print(bool(0))\n", "print(bool(0.0))\n", "print(bool([]))\n", "print(bool([4, 'hello', 1]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are also other data types in Python, which we want to mention here. In the following, we introduce **sets**, which are unordered collections of unique elements. Furthermore, we apply some basic set operations. " ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.903978Z", "iopub.status.busy": "2024-02-15T09:01:51.903803Z", "iopub.status.idle": "2024-02-15T09:01:51.907579Z", "shell.execute_reply": "2024-02-15T09:01:51.907081Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Print the set s: {1, 2, 4, 5}\n", "Union of sets: {1, 2, 3, 4}\n", "Intersection of sets: {2, 3}\n", "Adding an element {1, 2, 4, 5, 7}\n", "Removing an element {1, 4, 5, 7}\n" ] } ], "source": [ "s = {4, 2, 1, 2, 5, 2}\n", "print('Print the set s:', s)\n", "print('Union of sets:', {1, 2, 3} | {2, 3, 4})\n", "print('Intersection of sets:', {1, 2, 3} & {2, 3, 4})\n", "s.add(7)\n", "print('Adding an element', s)\n", "s.remove(2)\n", "print('Removing an element', s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another convenient data type are **dictionaries**, which are indexed by **keys** (rather than by a range of numbers as is the case for lists or arrays). The following code cell gives an examples and introduce some basic operations." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.910286Z", "iopub.status.busy": "2024-02-15T09:01:51.910070Z", "iopub.status.idle": "2024-02-15T09:01:51.913410Z", "shell.execute_reply": "2024-02-15T09:01:51.912911Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Print the dictionary dic: {'a': 1, 'b': 2, 3: 'hello'}\n", "Print the keys of dic: ['a', 'b', 3]\n", "Access the dic via a key: 2\n", "Print the values of dic: [1, 2, 'hello']\n" ] } ], "source": [ "dic = {'a': 1, 'b': 2, 3: 'hello'}\n", "print('Print the dictionary dic:', dic)\n", "print('Print the keys of dic:', list(dic.keys()))\n", "print('Access the dic via a key:', dic['b'])\n", "print('Print the values of dic:', list(dic.values()))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic Control Structures\n", "\n", "For control structures such as `if`, `for` or `while` one has to use indentations (as part of the syntax). A typical Python convention is to use four spaces. For example, an `if`-statement is written as follows:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.915925Z", "iopub.status.busy": "2024-02-15T09:01:51.915715Z", "iopub.status.idle": "2024-02-15T09:01:51.918600Z", "shell.execute_reply": "2024-02-15T09:01:51.918059Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "n = 2\n", "if n == 2:\n", " print('True')\n", "else:\n", " print('False')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The next example shows how to use a `for`-loop. Note that an iterable may be specified by a range, a list, a tuple, or even other structures." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.920963Z", "iopub.status.busy": "2024-02-15T09:01:51.920787Z", "iopub.status.idle": "2024-02-15T09:01:51.924179Z", "shell.execute_reply": "2024-02-15T09:01:51.923685Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0-1-2-\n", "a-2-c-def-\n", "a-b-c-d-\n" ] } ], "source": [ "for i in range(3):\n", " print(i, end='-')\n", "print()\n", " \n", "for i in ['a', 2, 'c', 'def']:\n", " print(i, end='-')\n", "print()\n", "\n", "for i in 'abcd':\n", " print(i, end='-')\n", "print()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A `while`-loop is written as follows:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.926760Z", "iopub.status.busy": "2024-02-15T09:01:51.926511Z", "iopub.status.idle": "2024-02-15T09:01:51.929492Z", "shell.execute_reply": "2024-02-15T09:01:51.928978Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0-1-2-3-4-" ] } ], "source": [ "a = 0\n", "while a < 5:\n", " print(a, end='-')\n", " a += 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Functions\n", "\n", "One defines functions with the `def`-keyword. As variable names, function names may contain letters (`a`, `b`, ..., `Y`, `Z`) and the underscore (`_`). All but the first character can also be positive integer number. Usually one uses lower case letters and underscores to separate words. The following function is named `add`. It has three arguments `a`, `b`, and `c` (with `b` and `c` having a default value). The `return` keyword is succeeded by the return value." ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.931981Z", "iopub.status.busy": "2024-02-15T09:01:51.931766Z", "iopub.status.idle": "2024-02-15T09:01:51.935783Z", "shell.execute_reply": "2024-02-15T09:01:51.935258Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Addition: 5 + 0 + 0 = 5\n", "5\n", "Addition: 5 + 2 + 1 = 8\n", "8\n", "Addition: 5 + 0 + 4 = 9\n", "9\n" ] } ], "source": [ "def add(a, b=0, c=0):\n", " \"\"\"Function to add three numbers\n", "\n", " | Notebook: B/B_libfmp.ipynb and\n", " | Notebook: B/B_PythonBasics.ipynb\n", "\n", " Args:\n", " a (float): First number\n", " b (float): Second number (default: 0)\n", " c (float): Third number (default: 0)\n", "\n", " Returns:\n", " d (float): Sum\n", " \"\"\"\n", " d = a + b + c\n", " print('Addition: ', a, ' + ', b, ' + ', c, ' = ', d)\n", " return d\n", "\n", "print(add(5))\n", "print(add(5, 2, 1))\n", "print(add(5, c=4))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There can also be multiple return values (which are returned as a tuple):" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.938342Z", "iopub.status.busy": "2024-02-15T09:01:51.938125Z", "iopub.status.idle": "2024-02-15T09:01:51.941330Z", "shell.execute_reply": "2024-02-15T09:01:51.940853Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(8, -2)\n" ] } ], "source": [ "def add_and_diff(a, b=0):\n", " \"\"\"Function to add and substract two numbers\n", " \n", " Notebook: B/B_PythonBasics.ipynb\n", " \n", " Args:\n", " a: first number\n", " b: second number (default: 0)\n", " \n", " Returns:\n", " first: a + b\n", " second: a - b\n", " \"\"\"\n", " return a + b, a - b\n", "\n", "x = add_and_diff(3, 5)\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## NumPy Arrays\n", "\n", "Python has several useful built-in packages as well as additional external packages. One such package is **NumPy**, which adds support for multi-dimensional arrays and matrices, along with a number of mathematical functions to operate on these structures, see [NumPy Reference Manual](https://docs.scipy.org/doc/numpy/reference/) for details. The NumPy package is imported as follows:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:51.943857Z", "iopub.status.busy": "2024-02-15T09:01:51.943648Z", "iopub.status.idle": "2024-02-15T09:01:52.791779Z", "shell.execute_reply": "2024-02-15T09:01:52.791105Z" } }, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is convenient to bind a package to a short name (for example `np` as above). This short name appears as prefix when calling a function from the package. This is illustrated by the following `array`-function provided by numpy:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:52.795459Z", "iopub.status.busy": "2024-02-15T09:01:52.795017Z", "iopub.status.idle": "2024-02-15T09:01:52.798787Z", "shell.execute_reply": "2024-02-15T09:01:52.798221Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1 2 3 3]\n" ] } ], "source": [ "x = np.array([1, 2, 3, 3])\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Each array has a shape, a type, and a dimension. " ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:52.801682Z", "iopub.status.busy": "2024-02-15T09:01:52.801460Z", "iopub.status.idle": "2024-02-15T09:01:52.805214Z", "shell.execute_reply": "2024-02-15T09:01:52.804491Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Shape: (4,)\n", "Type: int64\n", "Dimension: 1\n" ] } ], "source": [ "print('Shape:', x.shape)\n", "print('Type:', x.dtype)\n", "print('Dimension:', x.ndim)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example, note that `x.shape` produces a one-element tuple, which is encoded by `(4,)` for disambiguation. (The object `(4)` would be an integer of type `int` rather than a tuple.) Multi-dimensional arrays are created like follows:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:52.808080Z", "iopub.status.busy": "2024-02-15T09:01:52.807844Z", "iopub.status.idle": "2024-02-15T09:01:52.812145Z", "shell.execute_reply": "2024-02-15T09:01:52.811405Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x = \n", "[[ 1 2 33]\n", " [44 5 6]]\n", "Shape: (2, 3)\n", "Type: int64\n", "Dimension: 2\n" ] } ], "source": [ "x = np.array([[1, 2, 33], [44, 5, 6]])\n", "print('x = ', x, sep='\\n')\n", "print('Shape:', x.shape)\n", "print('Type:', x.dtype)\n", "print('Dimension:', x.ndim)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are a couple of functions for creating arrays:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:52.815279Z", "iopub.status.busy": "2024-02-15T09:01:52.815042Z", "iopub.status.idle": "2024-02-15T09:01:52.820786Z", "shell.execute_reply": "2024-02-15T09:01:52.820115Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Array of given shape and type, filled with zeros: [0. 0.]\n", "Array of given shape and type, filled with integer zeros: [0 0]\n", "Array of given shape and type, filled with ones: \n", "[[1. 1. 1.]\n", " [1. 1. 1.]]\n", "Evenly spaced values within a given interval: [2 4 6]\n", "Random values in a given shape: \n", "[[0.64630379 0.81998005 0.28367627]\n", " [0.75657033 0.72372747 0.85203454]]\n", "Identity matrix: \n", "[[1. 0. 0.]\n", " [0. 1. 0.]\n", " [0. 0. 1.]]\n" ] } ], "source": [ "print('Array of given shape and type, filled with zeros: ', np.zeros(2))\n", "print('Array of given shape and type, filled with integer zeros: ', np.zeros(2, dtype='int'))\n", "print('Array of given shape and type, filled with ones: ', np.ones((2, 3)), sep='\\n')\n", "print('Evenly spaced values within a given interval: ', np.arange(2, 8, 2))\n", "print('Random values in a given shape: ', np.random.rand(2, 3), sep='\\n')\n", "print('Identity matrix: ', np.eye(3), sep='\\n')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Reshaping of an array is possible like follows:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:52.824485Z", "iopub.status.busy": "2024-02-15T09:01:52.824105Z", "iopub.status.idle": "2024-02-15T09:01:52.829715Z", "shell.execute_reply": "2024-02-15T09:01:52.829047Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Shape: (24,)\n", "[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]\n", "Shape: (3, 8)\n", "[[ 0 1 2 3 4 5 6 7]\n", " [ 8 9 10 11 12 13 14 15]\n", " [16 17 18 19 20 21 22 23]]\n", "Shape: (3, 2, 4)\n", "[[[ 0 1 2 3]\n", " [ 4 5 6 7]]\n", "\n", " [[ 8 9 10 11]\n", " [12 13 14 15]]\n", "\n", " [[16 17 18 19]\n", " [20 21 22 23]]]\n", "Element y[0, 1, 2] = 6\n" ] } ], "source": [ "x = np.arange(2 * 3 * 4)\n", "print('Shape:', x.shape)\n", "print(x)\n", "\n", "y = x.reshape((3, 8))\n", "print('Shape:', y.shape)\n", "print(y)\n", "\n", "y = x.reshape((3, 2, 4))\n", "print('Shape:', y.shape)\n", "print(y)\n", "\n", "print('Element y[0, 1, 2] = ', y[0, 1, 2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "NumPy allows for giving one of the new shape parameter as `-1`. In this case, NumPy automatically figures out the unknown dimension. Note that in the following example the difference between the shape `(6,)` and the shape `(6, 1)`." ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:52.832875Z", "iopub.status.busy": "2024-02-15T09:01:52.832601Z", "iopub.status.idle": "2024-02-15T09:01:52.836655Z", "shell.execute_reply": "2024-02-15T09:01:52.836087Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Shape: (6,); dim: 1\n", "Shape: (3, 2); dim: 2\n", "Shape: (6, 1); dim: 2\n" ] } ], "source": [ "x = np.arange(6)\n", "print('Shape: %6s; dim: %s' % (x.shape, x.ndim))\n", "x = x.reshape(-1, 2)\n", "print('Shape: %6s; dim: %s' % (x.shape, x.ndim))\n", "x = x.reshape(-1, 1)\n", "print('Shape: %6s; dim: %s' % (x.shape, x.ndim))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Applied to arrays, many operations are conducted in an element-wise fashion:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:52.839539Z", "iopub.status.busy": "2024-02-15T09:01:52.839329Z", "iopub.status.idle": "2024-02-15T09:01:52.843048Z", "shell.execute_reply": "2024-02-15T09:01:52.842392Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x + 1 = [1 2 3 4 5]\n", "x * 2 = [0 2 4 6 8]\n", "x > 2 = [False False False True True]\n" ] } ], "source": [ "x = np.arange(5)\n", "print('x + 1 =', x + 1)\n", "print('x * 2 =', x * 2)\n", "print('x > 2 =', x > 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, applied to two arrays of the same shape, these operations are conducted in an element-wise fashion. Matrix multiplication is performed by using the function `np.dot`:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:52.845581Z", "iopub.status.busy": "2024-02-15T09:01:52.845385Z", "iopub.status.idle": "2024-02-15T09:01:52.849885Z", "shell.execute_reply": "2024-02-15T09:01:52.849318Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[0 1]\n", " [2 3]]\n", "[[2. 2.]\n", " [2. 2.]]\n", "[[2. 3.]\n", " [4. 5.]]\n", "[[0. 2.]\n", " [4. 6.]]\n", "[[ 2. 2.]\n", " [10. 10.]]\n" ] } ], "source": [ "a = np.arange(0, 4).reshape((2, 2))\n", "b = 2 * np.ones((2, 2))\n", "\n", "print(a)\n", "print(b)\n", "print(a + b)\n", "print(a * b)\n", "print(np.dot(a, b))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that arrays and lists may behave in a completely different way. For example, addition leads to the following results:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:52.852465Z", "iopub.status.busy": "2024-02-15T09:01:52.852251Z", "iopub.status.idle": "2024-02-15T09:01:52.855758Z", "shell.execute_reply": "2024-02-15T09:01:52.855147Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0 2 4 6] \n", "[0, 1, 2, 3, 0, 1, 2, 3] \n" ] } ], "source": [ "a = np.arange(4)\n", "b = np.arange(4)\n", "print(a + b, type(a + b))\n", "\n", "a = list(a)\n", "b = list(b)\n", "print(a + b, type(a + b))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The sum of an array's elements can be computed as follows:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:52.858167Z", "iopub.status.busy": "2024-02-15T09:01:52.857978Z", "iopub.status.idle": "2024-02-15T09:01:52.861619Z", "shell.execute_reply": "2024-02-15T09:01:52.861038Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[0 1 2]\n", " [3 4 5]]\n", "15\n", "[3 5 7]\n", "[ 3 12]\n" ] } ], "source": [ "x = np.arange(6).reshape((2, 3))\n", "print(x)\n", "print(x.sum())\n", "print(x.sum(axis=0))\n", "print(x.sum(axis=1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are many ways for accessing and manipulating arrays:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:52.864066Z", "iopub.status.busy": "2024-02-15T09:01:52.863879Z", "iopub.status.idle": "2024-02-15T09:01:52.867854Z", "shell.execute_reply": "2024-02-15T09:01:52.867310Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[0 1 2]\n", " [3 4 5]]\n", "4\n", "[array([[False, False, True],\n", " [ True, True, True]])]\n", "[2 3 4 5]\n", "[3 4 5]\n", "[1 4]\n" ] } ], "source": [ "x = np.arange(6).reshape((2, 3))\n", "print(x)\n", "print(x[1, 1])\n", "print([x > 1])\n", "print(x[x > 1])\n", "print(x[1, :])\n", "print(x[:, 1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "NumPy offers many different numerical types and methods for type conversion. Specifying the exact type is often important when using packages such as `numba` for optimizing machine code at runtime. In the following example, we give an example where a wrong initialization leads to an error when computing the square root of a negative number." ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:52.870494Z", "iopub.status.busy": "2024-02-15T09:01:52.870302Z", "iopub.status.idle": "2024-02-15T09:01:52.874603Z", "shell.execute_reply": "2024-02-15T09:01:52.873990Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "=== Initialization with 'int32' leading to an error ===\n", "[-2 -1 0 1] int64\n", "[nan nan 0. 1.]\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ ":4: RuntimeWarning: invalid value encountered in sqrt\n", " x = np.sqrt(x)\n" ] } ], "source": [ "print('=== Initialization with \\'int32\\' leading to an error ===', flush=True)\n", "x = np.arange(-2, 2)\n", "print(x, x.dtype)\n", "x = np.sqrt(x)\n", "print(x) " ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:01:52.877664Z", "iopub.status.busy": "2024-02-15T09:01:52.877434Z", "iopub.status.idle": "2024-02-15T09:01:52.882134Z", "shell.execute_reply": "2024-02-15T09:01:52.881496Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "=== Initialization with 'complex' ===\n", "[-3.+0.j -2.+0.j -1.+0.j 0.+0.j 1.+0.j 2.+0.j] complex128\n", "[0. +1.73205081j 0. +1.41421356j 0. +1.j\n", " 0. +0.j 1. +0.j 1.41421356+0.j ]\n" ] } ], "source": [ "print('=== Initialization with \\'complex\\' ===', flush=True)\n", "x = np.arange(-3, 3, dtype='complex')\n", "print(x, x.dtype)\n", "x = np.sqrt(x)\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "Acknowledgment: This notebook was created by Frank Zalkow, Stefan Balke, and Meinard Müller.\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "
\"C0\"\"C1\"\"C2\"\"C3\"\"C4\"\"C5\"\"C6\"\"C7\"\"C8\"
" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.8.16" } }, "nbformat": 4, "nbformat_minor": 1 }