10 + 313
Woche 2
9. Oktober 2025
Python ermöglicht alle grundlegenden mathematischen Berechnungen, die auch auf einem Taschenrechner durchgeführt werden können, mit einer Syntax1, die einem z.B. durch Microsoft Excel zumindest teilweise geläufig ist.
Die Operatoren für Addition, Subtraktion, Multiplikation und Division sind erwartungsgemäß:
Für die Potenzierung wird ** genutzt:
Mathematische Ausdrücke in Python folgen der normalen arithmetischen Reihenfolge der Operationen, also
*** und /
+ und -
Es können aber Klammern eingesetzt werden um eine andere Reihenfolge zu erreichen:
Der Vollständigkeit halber soll erwähnt sein, dass es weitere, nicht so gängige Operatoren gibt. Beispielsweise wird mit // erst dividiert und dann der Quotient auf die nächste ganze Zahl abgerundet, sodass 10 // 3 = 3. Mit dem Modulus-Operator % hingegen wird der Rest, der bei der Division zweier Zahlen entsteht, zurückgegeben, sodass 10 % 4 = 2.
Funktionen in Python, ähnlich wie in Excel, sind vordefinierte Operationen, die bestimmte Aufgaben ausführen und dabei oft Eingaben (Argumente) benötigen. Die Syntax einer Funktion besteht aus ihrem Namen, gefolgt von Klammern, in denen die Argumente übergeben werden.
Erstes Beispiel sei die round() Funktion, welche in Basis-Python enthalten ist und mit der Zahlen standardmäßig auf die nächste ganze Zahl gerundet werden können. Man übergibt also eine Zahl als Argument und erhält die gerundete Zahl zurück. Die Funktion erlaubt aber auch ein zweites Argument, um auf eine bestimmte Dezimalstelle zu runden. Gibt man kein zweites Argument vor, so wird der entsprechende default-Wert verwendet, was in diesem Fall zu keiner Nachkommastelle führt.
Fügt man eine Raute # in den Code ein, so wird alles, was in derselben Zeile danach kommt, als Kommentar interpretiert und nicht ausgeführt. Kommentare sind demnach sozusagen nur für Menschen und nicht für den Computer. Kommentare sind eine Möglichkeit, um den Code zu dokumentieren, übersichtlicher zu machen und zu erklären, was er tut.
Da wir Jupyter Notebooks inklusive Markdown-Zellen verwenden, kann argumentiert werden, dass diese #-Kommentare innerhalb des Codes weniger nützlich sind. Nichtsdestotrotz können sie eine gute Ergänzung sein. Außerdem muss auch klar sein, dass nicht alle Python-Programmierer eine Jupyter-Umgebung verwenden und demnach nur ggf. #-Kommentare und eben keine Markdown-Kommentare verwenden können.
Zwar können wir Argumente wie oben gezeigt einfach in der richtigen Reihenfolge getrennt durch Kommas übergeben, tatsächlich hat jedes Argument aber auch einen Namen, der in der Funktionssignatur definiert ist. Um die Argumentnamen einer Funktion in Erfahrung zu bringen, kann die Funktion help() verwendet werden:
Help on built-in function round in module builtins:
round(number, ndigits=None)
Round a number to a given precision in decimal digits.
The return value is an integer if ndigits is omitted or None. Otherwise
the return value has the same type as the number. ndigits may be negative.
Das erste Argument heißt demnach number und das zweite ndigits. Wir können auch die Argumentnamen explizit angeben. Dies macht zum Einen den Code ggf. besser lesbar, zum Anderen können wir die Argumente dann auch in beliebiger Reihenfolge übergeben. Anders ausgedrückt: Nur wenn wir die Argumente explizit benennen, können wir sie in beliebiger Reihenfolge übergeben. Geben wir keine Argumentnamen an, so müssen wir die Argumente in der Reihenfolge übergeben, in der sie in der Funktionssignatur definiert sind.
Schließlich sei noch erwähnt, dass auch eine negative Zahl an ndigits übergeben werden, um auf eine 10er-Stelle zu runden:
Selbstverständlich ist es auch möglich z.B. den Logarithmus einer Zahl zu berechnet. Allerdings gibt es dafür keine direkt verfügbare Funktion, sondern wir müssen auf ein Modul zurückgreifen, das diese Funktion enthält. Diese und andere Funktionen sind im Standardmodul math enthalten, sodass wir dieses zwar nicht installieren, wohl aber zunächst laden müssen.
Erst nachdem wir diesen Code zum laden des Moduls haben laufen lassen, können wir die Funktion math.log() verwenden, um den Logarithmus einer Zahl zu berechnen. Demnach müssen wir hier das Modul math voranstellen und mit einem . mit der eigentlichen Funktion log() verbinden.
Für besseren Lesefluss wird hier vorerst nicht detaillierter auf Module eingangen. Eine detailliertere Einführung kommt in einem späteren Kapitel.
Standardmäßig wird der natürliche Logarithmus von 100 berechnet, wobei die Basis des Logarithmus die Euler’sche Zahl \(e\) (≈ 2,718) ist. Es kann aber auch der Logarithmus zu einer beliebigen Basis berechnet werden, solange die als zweites Argument in der Funktion angegeben wird:
Analog kann auch die Exponentialfunktion (\(e^x\)) berechnet werden, wobei \(e\) wieder die Euler’sche Zahl ist. Schließlich kann auch die Quadratwurzel \(\sqrt(x)\) gezogen werden:
Es können auch math.ceil() und math.floor() verwendet werden, um immer auf- bzw. abzurunden.
Wie gerade gesehen, sind nicht alle Funktionen in Python direkt verfügbar. Stattdessen haben wir uns gerade einige zusätzliche Funktionen verfügbar gemacht, indem wir das math-Modul geladen haben. Module sind Sammlungen von Funktionen und Klassen, die in Python-Dateien gespeichert sind. Das math Modul ist dabei in der Python Standard Library enthalten, also direkt nach Installation von Python verfügbar - muss aber eben noch geladen bzw. aktiviert werden.
Darüber hinaus gibt es viele Module, die von Dritten erstellt wurden und einmalig installiert werden müssen, bevor sie geladen und verwendet werden können. Die Installation solcher Module erfolgt dabei z.B. über den Befehl pip install (siehe Python Package Index (PyPI); später mehr). Eigentlich gehören viele der Module, die wir in diesem Kurs verwenden werden, zu diesen sogenannten Third-Party-Modulen, sodass wir sie erst installieren müssten. Da wir aber Python via Anaconda verwenden, sind viele dieser Module bereits installiert und können direkt verwendet werden.
Es sei noch erwähnt, dass statt “Modul” in diesem Kontext auch Begriffe wie “Bibliothek” oder “Paket/Package” verwendet werden. Diese Begriffe sind mehr oder weniger Synonyme, wobei “Modul” eher für einzelne Dateien steht, “Bibliothek” für eine Sammlung von Modulen und “Paket/Package” für eine Sammlung von Bibliotheken. So ist z.B. pandas ein einzelnes Modul, wohingegen scikit-learn eine Bibliothek/ein Paket aus mehreren Modulen ist.
Oben ist für math eine gängige Art gezeigt, ein Modul zu laden und dessen Funktionen zu nutzen. Hier sind alle Möglichkeiten, wie ein Modul geladen werden kann:
Option 1
Modul mit import laden und Funktion mittels Punkt-Notation nutzen.
Option 3a
Spezifische Funktion aus Modul via from und import laden und direkt nutzen. Option a: Funktionsnamen in einer Zeile durch Kommas getrennt.
Option 4
Alle Funktionen aus Modul via from und import * laden und direkt nutzen.
Optionen 1 und 2 sind die gängigsten und empfohlenen, da sie zwar mehr Code benötigen, dafür aber stets klar ist, welche Funktionen aus welchem Modul stammen. Das ist nicht nur für die Menschen nachvollziehbarer, sondern vermeidet darüber hinaus noch sogenannte Namenskonflikte. Ein Namenskonflikt tritt auf, wenn zwei der geladenen Module (zufälligerweise) Funktionen mit demselben Namen haben. In diesem Fall würde Python automatisch die Funktion des zuletzt geladenen Moduls verwenden, was zu unerwarteten Ergebnissen führen kann.
Darüber hinaus sind sogar die Aliase (Option 2) für bestimmte Module so gängig, dass sie in der Python-Community als “Standard” gelten. So wird z.B. import pandas as pd und import numpy as np so häufig verwendet, dass es fast schon ungewöhnlich wäre, es nicht zu tun.
Syntax ist ein Satz von Regeln, die festlegen, wie Code geschrieben werden muss, damit der Computer ihn verstehen kann. Es ist wie die Grammatik für Computercode.↩︎
---
title: Mathematische Operatoren & Funktionen
author: "Woche 2"
---
Python ermöglicht alle grundlegenden mathematischen Berechnungen, die auch auf einem Taschenrechner durchgeführt werden können, mit einer Syntax[^1], die einem z.B. durch Microsoft Excel zumindest teilweise geläufig ist.
[^1]: Syntax ist ein Satz von Regeln, die festlegen, wie Code geschrieben werden muss, damit der Computer ihn verstehen kann. Es ist wie die Grammatik für Computercode.
# Symbolische Operatoren
Die Operatoren für Addition, Subtraktion, Multiplikation und Division sind erwartungsgemäß:
:::: {.grid}
::: {.g-col-3}
```{python}
10 + 3
```
:::
::: {.g-col-3}
```{python}
10 - 3
```
:::
::: {.g-col-3}
```{python}
10 * 3
```
:::
::: {.g-col-3}
```{python}
10 / 3
```
:::
::::
Für die Potenzierung wird `**` genutzt:
```{python}
10 ** 3
```
Mathematische Ausdrücke in Python folgen der normalen arithmetischen Reihenfolge der Operationen, also
1. `**`
2. `*` und `/`
3. `+` und `-`
Es können aber Klammern eingesetzt werden um eine andere Reihenfolge zu erreichen:
:::: {.grid}
::: {.g-col-6}
```{python}
1 + 2 * 3 ** 2
```
:::
::: {.g-col-6}
```{python}
((1 + 2) * 3) ** 2
```
:::
::::
Der Vollständigkeit halber soll erwähnt sein, dass es weitere, nicht so gängige Operatoren gibt. Beispielsweise wird mit `//` erst dividiert und dann der Quotient auf die nächste ganze Zahl abgerundet, sodass `10 // 3` = 3. Mit dem Modulus-Operator `%` hingegen wird der Rest, der bei der Division zweier Zahlen entsteht, zurückgegeben, sodass `10 % 4` = 2.
# Funktionen
Funktionen in Python, ähnlich wie in Excel, sind vordefinierte Operationen, die bestimmte Aufgaben ausführen und dabei oft Eingaben (Argumente) benötigen. Die Syntax einer Funktion besteht aus ihrem Namen, gefolgt von Klammern, in denen die Argumente übergeben werden.
Erstes Beispiel sei die `round()` Funktion, welche in Basis-Python enthalten ist und mit der Zahlen standardmäßig auf die nächste ganze Zahl gerundet werden können. Man übergibt also eine Zahl als Argument und erhält die gerundete Zahl zurück. Die Funktion erlaubt aber auch ein zweites Argument, um auf eine bestimmte Dezimalstelle zu runden. Gibt man kein zweites Argument vor, so wird der entsprechende default-Wert verwendet, was in diesem Fall zu keiner Nachkommastelle führt.
:::: {.grid}
::: {.g-col-6}
```{python}
# keine Nachkommastelle
round(123.456)
```
:::
::: {.g-col-6}
```{python}
# zwei Nachkommastellen
round(123.456, 2)
```
:::
::::
::: callout-note
Fügt man eine Raute `#` in den Code ein, so wird alles, was in derselben Zeile danach kommt, als **Kommentar** interpretiert und nicht ausgeführt. Kommentare sind demnach sozusagen nur für Menschen und nicht für den Computer. Kommentare sind eine Möglichkeit, um den Code zu dokumentieren, übersichtlicher zu machen und zu erklären, was er tut.
Da wir Jupyter Notebooks inklusive Markdown-Zellen verwenden, kann argumentiert werden, dass diese `#`-Kommentare innerhalb des Codes weniger nützlich sind. Nichtsdestotrotz können sie eine gute Ergänzung sein. Außerdem muss auch klar sein, dass nicht alle Python-Programmierer eine Jupyter-Umgebung verwenden und demnach nur ggf. `#`-Kommentare und eben keine Markdown-Kommentare verwenden können.
:::
Zwar können wir Argumente wie oben gezeigt einfach in der richtigen Reihenfolge getrennt durch Kommas übergeben, tatsächlich hat jedes Argument aber auch einen Namen, der in der Funktionssignatur definiert ist. Um die Argumentnamen einer Funktion in Erfahrung zu bringen, kann die Funktion `help()` verwendet werden:
```{python}
help(round)
```
Das erste Argument heißt demnach `number` und das zweite `ndigits`. Wir können auch die Argumentnamen explizit angeben. Dies macht zum Einen den Code ggf. besser lesbar, zum Anderen können wir die Argumente dann auch in beliebiger Reihenfolge übergeben. Anders ausgedrückt: Nur wenn wir die Argumente explizit benennen, können wir sie in beliebiger Reihenfolge übergeben. Geben wir keine Argumentnamen an, so müssen wir die Argumente in der Reihenfolge übergeben, in der sie in der Funktionssignatur definiert sind.
Schließlich sei noch erwähnt, dass auch eine negative Zahl an `ndigits` übergeben werden, um auf eine 10er-Stelle zu runden:
:::: {.grid}
::: {.g-col-6}
```{python}
round(123.456, -1)
```
:::
::: {.g-col-6}
```{python}
round(ndigits = -1, number = 123.456)
```
:::
::::
Selbstverständlich ist es auch möglich z.B. den Logarithmus einer Zahl zu berechnet. Allerdings gibt es dafür keine direkt verfügbare Funktion, sondern wir müssen auf ein *Modul* zurückgreifen, das diese Funktion enthält. Diese und andere Funktionen sind im Standardmodul `math` enthalten, sodass wir dieses zwar nicht installieren, wohl aber zunächst laden müssen.
```{python}
import math # Das math-Modul laden
```
Erst nachdem wir diesen Code zum laden des Moduls haben laufen lassen, können wir die Funktion `math.log()` verwenden, um den Logarithmus einer Zahl zu berechnen. Demnach müssen wir hier das Modul `math` voranstellen und mit einem `.` mit der eigentlichen Funktion `log()` verbinden.
::: callout-note
Für besseren Lesefluss wird hier vorerst nicht detaillierter auf Module eingangen. Eine detailliertere Einführung kommt in einem späteren Kapitel.
:::
Standardmäßig wird der *natürliche* Logarithmus von 100 berechnet, wobei die Basis des Logarithmus die [Euler'sche Zahl](https://www.wikiwand.com/de/Eulersche_Zahl) $e$ (≈ 2,718) ist. Es kann aber auch der Logarithmus zu einer beliebigen Basis berechnet werden, solange die als zweites Argument in der Funktion angegeben wird:
:::: {.grid}
::: {.g-col-6}
```{python}
# Logarithmus zur Basis e
math.log(100)
```
:::
::: {.g-col-6}
```{python}
# Logarithmus zur Basis 10
math.log(100, 10)
```
:::
::::
Analog kann auch die Exponentialfunktion ($e^x$) berechnet werden, wobei $e$ wieder die Euler'sche Zahl ist. Schließlich kann auch die Quadratwurzel $\sqrt(x)$ gezogen werden:
:::: {.grid}
::: {.g-col-6}
```{python}
math.exp(10)
```
:::
::: {.g-col-6}
```{python}
math.sqrt(9)
```
:::
::::
Es können auch `math.ceil()` und `math.floor()` verwendet werden, um immer auf- bzw. abzurunden.
:::: {.grid}
::: {.g-col-6}
```{python}
# Aufrunden
math.ceil(123.456)
```
:::
::: {.g-col-6}
```{python}
# Abrunden
math.floor(123.456)
```
:::
::::
# Module
Wie gerade gesehen, sind nicht alle Funktionen in Python direkt verfügbar. Stattdessen haben wir uns gerade einige zusätzliche Funktionen verfügbar gemacht, indem wir das `math`-Modul geladen haben. Module sind Sammlungen von Funktionen und Klassen, die in Python-Dateien gespeichert sind. Das `math` Modul ist dabei in der [Python Standard Library](https://docs.python.org/3/library/) enthalten, also direkt nach Installation von Python verfügbar - muss aber eben noch geladen bzw. aktiviert werden.
Darüber hinaus gibt es viele Module, die von Dritten erstellt wurden und einmalig installiert werden müssen, bevor sie geladen und verwendet werden können. Die Installation solcher Module erfolgt dabei z.B. über den Befehl `pip install` (siehe [Python Package Index](https://pypi.org/) (PyPI); später mehr). Eigentlich gehören viele der Module, die wir in diesem Kurs verwenden werden, zu diesen sogenannten *Third-Party-Modulen*, sodass wir sie erst installieren müssten. Da wir aber Python via Anaconda verwenden, sind viele dieser Module bereits installiert und können direkt verwendet werden.
Es sei noch erwähnt, dass statt "Modul" in diesem Kontext auch Begriffe wie "Bibliothek" oder "Paket/Package" verwendet werden. Diese Begriffe sind mehr oder weniger Synonyme, wobei "Modul" eher für einzelne Dateien steht, "Bibliothek" für eine Sammlung von Modulen und "Paket/Package" für eine Sammlung von Bibliotheken. So ist z.B. `pandas` ein einzelnes Modul, wohingegen `scikit-learn` eine Bibliothek/ein Paket aus mehreren Modulen ist.
## Importieren von Modulen
Oben ist für `math` eine gängige Art gezeigt, ein Modul zu laden und dessen Funktionen zu nutzen. Hier sind alle Möglichkeiten, wie ein Modul geladen werden kann:
:::: {.grid}
::: {.g-col-6}
**Option 1**
Modul mit `import` laden und Funktion mittels Punkt-Notation nutzen.
```{python}
import math
math.sqrt(9 + math.pi)
```
:::
::: {.g-col-6}
**Option 2**
Modul mit `import` und `as` unter einem anderen Namen (Alias) laden und Funktion mittels Punkt-Notation nutzen.
```{python}
import math as m
m.sqrt(9 + m.pi)
```
:::
::::
:::: {.grid}
::: {.g-col-6}
**Option 3a**
Spezifische Funktion aus Modul via `from` und `import` laden und direkt nutzen. Option a: Funktionsnamen in einer Zeile durch Kommas getrennt.
```{python}
from math import sqrt, pi
sqrt(9 + pi)
```
:::
::: {.g-col-6}
**Option 3b**
Spezifische Funktion aus Modul via `from` und `import` laden und direkt nutzen. Option b: Ein Funktionsname je Zeile durch Kommas getrennt und in Klammern.
```{python}
from math import (sqrt,
pi)
sqrt(9 + pi)
```
:::
::::
**Option 4**
Alle Funktionen aus Modul via `from` und `import *` laden und direkt nutzen.
```{python}
from math import *
sqrt(9 + pi)
```
::: callout-note
Optionen 1 und 2 sind die gängigsten und empfohlenen, da sie zwar mehr Code benötigen, dafür aber stets klar ist, welche Funktionen aus welchem Modul stammen. Das ist nicht nur für die Menschen nachvollziehbarer, sondern vermeidet darüber hinaus noch sogenannte Namenskonflikte. Ein Namenskonflikt tritt auf, wenn zwei der geladenen Module (zufälligerweise) Funktionen mit demselben Namen haben. In diesem Fall würde Python automatisch die Funktion des zuletzt geladenen Moduls verwenden, was zu unerwarteten Ergebnissen führen kann.
Darüber hinaus sind sogar die Aliase (Option 2) für bestimmte Module so gängig, dass sie in der Python-Community als "Standard" gelten. So wird z.B. `import pandas as pd` und `import numpy as np` so häufig verwendet, dass es fast schon ungewöhnlich wäre, es nicht zu tun.
:::
::: callout-tip
## Weitere Ressourcen
- [{{< fa brands youtube >}} What are Python modules?](https://youtu.be/XcfxkHrHTVE?si=QWink9LOEkAiKtyX) **nur bis 3:53!**
- [{{< fa brands youtube >}} Please NEVER Do THIS In Python :(](https://youtube.com/shorts/8eiaM85c_iI?si=6JyQTVfz18TLHYR7)
:::
# Übungen
::: {.webex-check .webex-box}
```{r}
#| echo: false
#| results: asis
q <- "Was ergibt round(111, -1)"
q_choices <- c("-1", answer="110", "111.0")
cat(q,longmcq(q_choices))
q <- "Was ergibt round(-1, 111)"
q_choices <- c(answer="-1", "110", "111.0")
cat(q,longmcq(q_choices))
q <- "Welcher dieser Befehle führt nicht zu dem gleichen Ergebnis der anderen drei?"
q_choices <- c(answer="round(1, 1.33)", "round(ndigits=1, number=1.33)", "round(1.33, 1)", "round(number=1.33, ndigits=1)")
cat(q,longmcq(q_choices))
```
:::