- Aktuelle Version: Python 3.5
- Interpretierte Programmiersprache
  - Kein Kompilieren
  - Programme werden mit dem `python`-Programm ausgeführt
- Eignet sich sehr gut zum Erlernen der Programmierung!
- Hat viele Pakete, die man für wissenschaftliche Arbeit gebrauchen kann

Hier soll es hingehen: Auswertung von Praktikumsversuchen:

Versuch aus dem Fortgeschrittenen-Praktikum: Lebensdauer kosmischer Myonen

# Python¶

Eine Programmiersprache wie Python lässt sich nicht an einem Tag lernen.

Hier geben wir einen kurzen Überblick über die wichtigsten Konzepte.

Keine Angst: Zum Erstellen von Plots und für einfache Auswertungen muss man nicht viel Python können!

Die folgenden Beispiele kann man auf der Kommandozeile durch ausführen von

    ipython

ausprobieren.

### Einfachstes Beispiel¶

In [1]:

    print('Hello, World!')

    Hello, World!

Zum Vergleich: C++

    #include <iostream>

    int main(int argc, char *argv[])
    {
        std::cout << "Hello, World!" << std::endl;
        return 0;
    }

## Kommentare¶

Sehr wichtig für die Leute, die mit euch Arbeiten und für euch zwei Wochen später, sind Kommentare, die erklären, was euer Code tut.

Alles was in Python hinter einem `#` steht, wird nicht als Code betrachtet und dient als Kommentar.

In [2]:

    # This just prints the traditional greeting to the console
    print("Hello, World!")

    Hello, World!

Kommentare sollten nicht erklären, was der Code tut, sondern warum.

Kommentare, wie jeder andere Code, sollten auf englisch sein.

## Variablen¶

- Man kann einem Objekt einen Namen geben:

In [3]:

    a = 2
    b = 3

Variablennamen können auch überschrieben werden:

In [4]:

    a = 42
    b = a

    a = 0
    b

Out[4]:

    42

## Einfache Datentypen¶

### None¶

Stellt das Fehlen eines Wertes dar.

Wird häufig für Standardwerte von Funktionen verwendet.

In [5]:

    print(None)

    None

Funktionen, die 'nichts' zurückgeben, geben `None` zurück:

In [6]:

    a = print('test')

    test

In [7]:

    print(a)

    None

### Booleans¶

`True` und `False`

Logische Operatoren: `and`, `or`, `not`

In [8]:

    True or False

Out[8]:

    True

`None` oder leere Objekte verhalte sich wie `False`, andere wie `True`

In [9]:

    None or 'Hallo'

Out[9]:

    'Hallo'

### Zahlen¶

Ganze Zahlen: `42` Kommazahlen: `3.14`

Rechenoperatoren:

- `+`, `-`, `*`
- `**` (Potenzieren: `2**3` → `8`)
- `/` (`3 / 2` → `1.5`)
- `//` (Ganzzahldivision: `3 // 2` → `1`)
- `%` (Modulo-Operation, Divisionsrest: `7 % 4` → `3`)

In [10]:

    x = 5
    y = 3
    x + y

Out[10]:

    8

Vergleichsoperatoren geben `True` oder `False` zurück

- `==`, `!=`
- `>`, `<`, `>=`, `<=`

In [11]:

    x < y

Out[11]:

    False

### Strings¶

Stehen in `'` oder `"`.

In [12]:

    foo = 'foo'
    bar = "bar"

Strings können mit `+` konkateniert werden:

In [13]:

    foo + " " + bar

Out[13]:

    'foo bar'

### Listen¶

Gedacht für mehrere Werte vom selben Typ.

In [14]:

    names = ['foo', 'bar']

In [15]:

    names[1]

Out[15]:

    'bar'

In [16]:

    names.append('baz')
    names

Out[16]:

    ['foo', 'bar', 'baz']

Listen werden mit `+` zusammengeführt:

In [17]:

    names + ['thing']

Out[17]:

    ['foo', 'bar', 'baz', 'thing']

Man kann die Liste auch erweitern:

In [18]:

    names.extend(['quux'])
    names

Out[18]:

    ['foo', 'bar', 'baz', 'quux']

In [19]:

    names[1] = 'new'
    names

Out[19]:

    ['foo', 'new', 'baz', 'quux']

Mit `in` prüft man, ob ein Wert in der Liste ist:

In [20]:

    weekdays = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
    'Mo' in weekdays

Out[20]:

    True

### Tupel¶

Gedacht für Werte mit unterschiedlichen Typen. Unveränderbar nach Erzeugung. Können wahlweise auch ohne Klammerngeschrieben werden (wenn es eindeutig ist).

In [21]:

    tup = 5, 3
    tup

Out[21]:

    (5, 3)

In [22]:

    tup[0]

Out[22]:

    5

In [23]:

    tup[1] = 7

    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-23-ac9eff4a13ef> in <module>()
    ----> 1 tup[1] = 7

    TypeError: 'tuple' object does not support item assignment

### Dictionaries¶

In [24]:

    numbers = { 'one': 1, 'two': 2, 'three': 3 }

In [25]:

    numbers['two']

Out[25]:

    2

Dictionaries sind extrem hilfreich, zum Beispiel um die gleiche Analyse für verschiedene Datensätze durchzuführen:

In [26]:

    data = {'Cu': [1.1, 1.2, 1.3, 1.4], 'Fe': [0.7, 0.8, 0.9, 1.0]}
    data['Cu']

Out[26]:

    [1.1, 1.2, 1.3, 1.4]

## Funktionen aufrufen¶

Mit Funktionen lässt sich Code leicht wiederverwenden. Eine Funktion nimmt Parameter, verarbeitet sie und gibt Ergebnisse zurück.

In [27]:

    print('Hello!')

    Hello!

In [28]:

    len([1, 2, 3, 4, 5])

Out[28]:

    5

Viele Funktionen haben mehrere Parameter, einige können sogar beliebig viele haben:

In [29]:

    print(1, 2, 3, 4, 5)

    1 2 3 4 5

Viele Funktionen haben optionale Parameter mit eigenem Namen, sogenannte "keyword arguments":

In [30]:

    print(1, 2, 3, sep=', ')

    1, 2, 3

Objekte haben auch Funktionen (nennt man Methoden):

In [31]:

    s = 'test'
    s.upper()

Out[31]:

    'TEST'

In [32]:

    'foo bar baz'.split()

Out[32]:

    ['foo', 'bar', 'baz']

In IPython kann man wie folgt auf die Dokumentation einer Funktion zugreifen:

In [33]:

    print?

Ansonsten findet man ausführliche Erklärungen in der offiziellen Dokumentation.

## Kontrollstrukturen¶

Die Zeilen eines Python-Programms werden nacheinander ausgeführt.

Sogennante Kontrollstrukturen erlauben es, den Ablauf zu steuern.

- `if`/`elif`/`else`: Je nach Bedingung unterschiedliche Befehle ausführen

In [34]:

    a = 3

    if a == 1:
        # muss eingerückt werden, 4 spaces:
        print('foo')
    elif a == 2:
        print('bar')
    else:
        print('baz')

    baz

- `while`-Schleifen: Wiederholen, solange ein bestimmter Ausdruck erfüllt ist.

In [35]:

    i = 0
    while i < 5:
        print(i)
        i += 1

    # there has to be a better way!

    0
    1
    2
    3
    4

- `for`-Schleifen: Wiederholen für jedes Element (z.B. einer Liste)

In [36]:

    data = [10, 42, -1]

    for x in data:
        # Wir können auf das jetztige Element als "x" zugreifen
        print(2 * x)

    20
    84
    -2

In [37]:

    for i in range(5):
        print(i)

    0
    1
    2
    3
    4

In [38]:

    for i in range(2, 5):
        print(i)

    2
    3
    4

In [39]:

    for i in range(10, 3, -1):
        print(i)

    10
    9
    8
    7
    6
    5
    4

In [40]:

    for day in weekdays:
        print("Heute ist", day)

    Heute ist Mo
    Heute ist Di
    Heute ist Mi
    Heute ist Do
    Heute ist Fr
    Heute ist Sa
    Heute ist So

Zwei sehr nützliche Funktionen sind `enumerate` und `zip`

In [41]:

    for i, day in enumerate(weekdays):
        print(day, " ist der ", i+1, ". Tag der Woche", sep="")

    Mo ist der 1. Tag der Woche
    Di ist der 2. Tag der Woche
    Mi ist der 3. Tag der Woche
    Do ist der 4. Tag der Woche
    Fr ist der 5. Tag der Woche
    Sa ist der 6. Tag der Woche
    So ist der 7. Tag der Woche

In [42]:

    english = ["foot", "ball", "goal"]
    german = ["Fuß", "Ball", "Tor"]

    for a, b in zip(english, german):
        print(a, b)

    foot Fuß
    ball Ball
    goal Tor

Das obere würde man eher so machen:

In [43]:

    translations = {
        'foot': 'Fuß',
        'ball': 'Ball',
        'goal': 'Tor',
    }

    for e, g in translations.items():
        print(e, g)

    goal Tor
    ball Ball
    foot Fuß

## Eigene Funktionen definieren mit `def`¶

Bevor man eine Funktion verwenden kann, muss sie erst definiert werden. Das wird wie folgt gemacht. Mit dem Keyword `return` kann man die Funktion beenden und Ergebnisse zurückgeben.

In [44]:

    def add(x, y):
        z = x + y
        return z

    add(2, 2)

Out[44]:

    4

Man kann auch mehrere Werte zurückgeben:

In [45]:

    def divide(x, y):
        return x // y, x % y

    n, rest = divide(5, 3)
    n, rest

Out[45]:

    (1, 2)

In [46]:

    def factorial(n):
        if n == 0:
            return 1
        else:
            return n * factorial(n - 1)

    factorial(4)

Out[46]:

    24

## Module und `import`¶

In Python kann man Programme in einzelne Module portionieren.

Es stehen bereits unglaublich viele Module für Python zur Verfügung. Gerade fürs wissenschaftliche Arbeiten ist eigentlich alles da was man braucht und noch viel mehr. Braucht man etwas aus einem anderen Modul, importiert man es:

In [47]:

    import os

    os.listdir()

Out[47]:

    ['README.md',
     'example2.txt',
     'example_data.txt',
     'muon_data.txt',
     'muon_plot.png',
     'uncertainties.ipynb',
     '.gitignore',
     'matplotlibrc',
     'matplotlib.ipynb',
     'Makefile',
     'muon_plot.py',
     'scientific-python.ipynb',
     'python.ipynb',
     'test.txt']

Man kann auch nur einzelne Funktionen importieren:

In [48]:

    from os.path import join
    outputpath = "Plots"
    join(outputpath, "fig1.pdf")

Out[48]:

    'Plots/fig1.pdf'

`from module import *` importiert jede Funktion eines Moduls. Sollte auf Grund von möglichen Mehrfachbelegungen nicht in größeren Programmen verwendet werden

In [49]:

    from os.path import *
    outputpath = "Plots"
    if exists(outputpath):
        print("Plots exists!")

Den Modulen können mit `as` neue Namen gegeben werden

In [50]:

    import os.path as pa

    pa.join(outputpath, "fig1.pdf")

Out[50]:

    'Plots/fig1.pdf'

## Auslagern in Python-Dateien¶

- Python-Dateien haben die Endung `.py`
- Startet man mit `python programm.py`
- Einzelne Python-Dateien (Endung `.py`) kann man als Module benutzen. Liegt eine Datei `test.py` im selben Ordner, so kann man `import test` ausführen.
- Die Datei sollte immer in der Codierung UTF-8 abgespeichert werden.

Es folgt ein fertiges Python-Programm.

Speichert es als `primes.py` ab und startet es aus dem Terminal mit `python primes.py`.

In [51]:

    def primes(max_num):
        # Only primes smaller than max_num are calculated
        is_prime = max_num * [True]
        is_prime[0] = False
        is_prime[1] = False

        primes = []

        # Sieve of Erathosthenes:
        for i in range(2, max_num):
            if is_prime[i]:
                for j in range(2 * i, max_num, i):
                    # Multiples are not primes
                    is_prime[j] = False
                primes.append(i)

        return primes

    print(primes(100))

    [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

## Besonderheiten bei Strings¶

Mit `\` kann man in Strings besondere Anweisungen setzen:

- `'\n'` -> Zeilenumbruch
- `'\t'` -> Tab
- `'\\'` -> normales `'\'`

Wenn man viele `'\'` schreiben muss (z.B. in LaTeX-Code), lohnt es sich diese Funktion mit dem Prefix `r` auszuschalten:

In [52]:

    print(r'\Huge\texttt{Python}')

    \Huge\texttt{Python}

Oft will man Werte oder andere Strings in einen String einsetzen.

Dafür stellt Python die mächtige `format()`-Methode bereit:

In [53]:

    'Erster Wert: {}, Zweiter Wert: {}'.format(42, 0)

Out[53]:

    'Erster Wert: 42, Zweiter Wert: 0'

Die `{}`-Markierungen werden durch die Parameter von `format()` ersetzt.

`format()` hat viele fortgeschrittene Funktionen:

In [54]:

    'Das Ergebnis ist {:.2f}'.format(3.2291421)

Out[54]:

    'Das Ergebnis ist 3.23'

Will man `{` oder `}` im Text stehen haben (gut für LaTeX) geht das mit doppelten `{{` oder `}}`.

LaTeX sieht dann leider so aus:

In [55]:

    print(r'\SI{{{:.4f}}}{{{:s}}}'.format(1.23456, r'\kilo\joule'))

    \SI{1.2346}{\kilo\joule}

Ausführliche Beispiele zur Benutzung von Format findet man z.B. in der offiziellen Dokumentation:

https://docs.python.org/3.1/library/string.html#format-examples

## Comprehensions¶

Sind nützlich, um Listen oder Dictionaries umzuwandeln oder zu erzeugen:

In [56]:

    [2 * x for x in range(5)]

Out[56]:

    [0, 2, 4, 6, 8]

In [57]:

    {num + 1: name for num, name in enumerate(weekdays)}

Out[57]:

    {1: 'Mo', 2: 'Di', 3: 'Mi', 4: 'Do', 5: 'Fr', 6: 'Sa', 7: 'So'}

In [58]:

    [x + y for y in range(3) for x in range(4) if x % 2 == 0]

Out[58]:

    [0, 2, 1, 3, 2, 4]