Python Einführungskurs für das Physikalische Anfängerpraktikum der Universität Heidelberg | Startseite


101 - Grundlagen der Programmierung in Python

Programmieren besteht aus einer Aneinanderreihung von Befehlen, die der Python Interpreter ausführt. Ein einfacher Befehl ist die Zuweisung eines Wertes zu einer Variablen:

In [ ]:
x = 1
# Diese Zelle auswählen und mit `<SHIFT> + <ENTER>` ausführen.
# Der letzte Rückgabewert der Zelle wird dann unten ausgegeben,
# hier also der Wert von `x`:
x

Hinweis: Dieses Kursmaterial besteht aus interaktiven Jupyter Notebooks. Jede Zelle, wie die obige, könnt ihr per Klick oder mit den Pfeiltasten auswählen und mit <SHIFT> + <ENTER> ausführen. Probiert's mal mit der Zelle oben!

Geht, um dem Kurs zu folgen, alle Zellen nacheinander durch und führt sie aus.

Wie hier demonstriert gibt das Jupyter Notebook immer den letzten Rückgabewert einer Zelle aus. Wir können auch die print() Funktion verwenden, um Ausgaben zu generieren:

In [ ]:
print(x)

Der Wert der Variable x ist nun der Integer 1. Werte haben immer einen Typ wie

  • int für ganze Zahlen, z.B. 1, 42, -10,
  • float für Fließkommazahlen, z.B. 0.5, 3.14, 1e10,
  • str für Zeichenketten (Strings), z.B. "Hello World!",
  • boolean für Wahrheitswerte (Booleans), also True und False

Die Typen der Python Standardlibrary findet ihr in der Dokumentation.

Da Variablen in Python nicht typisiert sind, können der gleichen Variable nacheinander Werte verschiedener Typen zugewiesen werden:

In [ ]:
type(x)
In [ ]:
x = 0.5
type(x)

Weiterhin können Werte in einen anderen Typ konvertiert werden:

In [ ]:
x = int(0.5) # Bei der Konvertierung zu int wird immer abgerundet!
x

Die grundlegenden Rechenoperationen +, -, *, / und ** sind ebenfalls in Python verfügbar und verhalten sich, wie man es erwartet:

In [ ]:
1 + 3
In [ ]:
3 / 2

Hinweis zu Python 2.x: Die Division zweier Integer gab vor Python 3 wieder einen abgerundeten Integer zurück, im obigen Beispiel also 3 / 2 = int(1.5) = 1. Damit sich die Division mit Python 2.x stattdessen wie in Python 3 verhält, kann diese zu Beginn des Skripts importiert werden:

from __future__ import division

Die Integer Division ist außerdem in Python 3 als Operator // verfügbar:

In [ ]:
3 // 2
In [ ]:
3**2

Aufgabe 1 - Werte und Typen

Der Operator zur Potenzierung ist in Python **. Weise einer Variablen y folgende Werte zu und lasse dir dann ihren Wert und Typ ausgeben. Stimmen Wert und Typ mit deinen Erwartungen überein?

a) $4^3$

Hinweis: Dies ist eine Übungsaufgabe. Verwende die Zelle unten, um sie zu lösen. Entferne dazu den Platzhalter-Code

# DEINE LÖSUNG HIER

und schreibe stattdessen den Code zur Lösung der Aufgabe.

In [ ]:
y = 4**3
y, type(y)

Hinweis: Auf die Lösung jeder Aufgabe folgt eine Test-Zelle wie die folgende, mit der du deine Lösung überprüfen kannst. Führe einfach diese Zelle aus. Wenn etwas an deiner Lösung nicht stimmt, erhälst du eine Fehlermeldung mit Hinweisen.

In [ ]:
from nose.tools import assert_equal
try:
    y
except NameError:
    raise NameError("Es gibt keine Variable 'y'. Weise den Wert einer Variablen mit diesem Namen zu.")
assert_equal(y, 64, "Die Variable hat nicht den richtigen Wert. Überprüfe deine Rechnung.")
print("👍 Sehr gut!")

b) $2+3.4^2$

In [ ]:
y = 2 + 3.4**2
y, type(y)
In [ ]:
from nose.tools import assert_equal
try:
    y
except NameError:
    raise NameError("Es gibt keine Variable 'y'. Weise den Wert einer Variablen mit diesem Namen zu.")
assert_equal(y, 2 + 3.4**2, "Die Variable hat nicht den richtigen Wert. Überprüfe deine Rechnung.")
print("Ok, du hast es verstanden.")

Strings

Strings sind Zeichenketten wie:

In [ ]:
s = "Hello World"

und werden in Python vom Typ str repräsentiert. Um einen String zu erstellen können wir einzelne ('), doppelte (") oder dreifache (''' oder """, für mehrzeilige Strings) Anführungszeichen verwenden, sodass das jeweils andere Anführungszeichen im String verwendet werden kann:

In [ ]:
s.count()
In [ ]:
"I'm"

Alternativ können Steuerzeichen im String auch escaped werden:

In [ ]:
"Say \"hi\""

Strings sind Reihen

Da Strings eine Aneinanderreihung von Elementen (in diesem Fall Textzeichen) darstellen, können viele Funktionen mit Strings verwendet werden, die mit Reihen arbeiten. Dazu gehören:

In [ ]:
len(s) # gibt die Zahl der Reihenelemente zurück
In [ ]:
s[0] # gibt das Element der Reihe an der Stelle 0 zurück
In [ ]:
s + "!" # Reihen können kombiniert werden

Strings sind Objekte

Die meisten "Dinge" in Python sind Objekte, d.h. neben ihrem Typ besitzen sie assoziierte Attribute und Methoden, auf die über einen Punkt . zugegriffen werden kann. Neben Strings sind bspw. auch Werte der anderen schon bekannten Datentypen wie int(5) und sogar Funktionen und die Datentypen selbst Objekte.

Ein Attribut eines Objekts ist eine Variable, die gelesen und gesetzt werden kann, wie bspw. x.shape. Eine Methode ist eine Funktion, die das Objekt zur Verfügung stellt, wie x.min().

Einige Beispiele für Methoden, die Strings zur Verfügung stellen, sind:

In [ ]:
s.upper()
In [ ]:
s.split()
In [ ]:
s.index('World')

Hinweis: In Jupyter Notebooks können wir die <TAB>-Vervollständigung verwenden um die assoziierten Attribute und Methoden eines Objekts zu inspizieren:

s = "Hello World"
# Zelle ausführen, dann:
s.<TAB> # `s.` tippen und die <TAB>-Taste drücken

Dies zeigt die verfügbaren Attribute und Methoden des Strings s an. Die <TAB>-Vervollständigung für eine Variable funktioniert erst nachdem die Variable erstellt wurde, also die Zelle einmal ausgeführt wurde.

Um herauszufinden, was eine Funktion oder Methode tut, könnt ihr im Jupyter Notebook ein Fragezeichen ? verwenden:

In [1]: s.split?
markdown
Docstring:
S.split(sep=None, maxsplit=-1) -> list of strings

Return a list of the words in S, using sep as the
delimiter string.  If maxsplit is given, at most maxsplit
splits are done. If sep is not specified or is None, any
whitespace string is a separator and empty strings are
removed from the result.
Type:      builtin_function_or_method

Schreibt ihr stattdessen zwei Fragezeichen ?? zeigt das Jupyter Notebook die gesamte Definition der Funktion oder Methode an.

Verwendet die <TAB>-Vervollständigung und die ?-Dokumentation häufig um hilfreiche Attribute und Methoden zu finden und zu verstehen!

Aufgabe 2 - Strings und Dokumentation

Finde im folgenden String mithilfe einer Methode, wie häufig der Buchstabe "A" auftaucht und weise den Wert einer Variable n zu. Probiere die <TAB>-Vervollständigung und die ?-Dokumentation aus um eine passende Methode zu finden.

In [ ]:
s = "CAGTACCAAGTGAAAGAT"
### BEGIN SOLUTION
n = s.count("A")
### END SOLUTION
print(n)
In [ ]:
from nose.tools import assert_equal
try:
    y
except NameError:
    raise NameError("Es gibt keine Variable 'n'. Weise den Wert einer Variablen mit diesem Namen zu.")
assert_equal(n, 8, "Das ist nicht die richtige Anzahl. Versuch's mal mit der `count` Methode!")
print("Klappt!")

String-Formatierung

Eine wichtige Methode ist str.format(), die markierte Platzhalter im String mit Werten ersetzt, die der Methode übergeben werden:

In [ ]:
x = 10
"Der Wert von x ist {}".format(x)

Ein Platzhalter wird durch eine öffnende { und schließende } geschweifte Klammer begrenzt und kann eine Bezeichnung des Platzhalters sowie Formatierungsoptionen beinhalten:

In [ ]:
"{raw_value} ist gerundet {rounded_value:.3f}.".format(raw_value=2/3, rounded_value=2/3)

Hinweis: Die vollständige Syntax der String-Formatierung ist in der Dokumentation einzusehen.

Aufgabe 3 - String Formatierung

Schreibe deinen Namen in die Variable name. Verwende dann die format Methode um aus s und name den Gruß "Hello World, mein Name ist __DEIN_NAME__!" zusammenzusetzen. Weise den zusammengesetzten String der Variable greeting zu.

In [ ]:
s = "Hello World"
name = "__DEIN_NAME__"
### BEGIN SOLUTION
greeting = s + ", mein Name ist {name}!".format(name=name)
### END SOLUTION
print(greeting)
In [ ]:
from nose.tools import assert_in
try:
    greeting
except NameError:
    raise NameError("Es gibt keine Variable 'greeting'. Weise den Wert einer Variablen mit diesem Namen zu.")
assert_in("mein Name ist", greeting)
print("Hello {}! 👋".format(name))

Listen und Tupel

Während Strings einzelne Zeichen aneinanderreihen, repräsentieren Listen und Tupel eine Reihe beliebiger Werte. Die Elemente einer Liste können verändert werden, während ein Tupel unveränderlich ist. Wir können Listen erstellen, indem wir die Elemente durch Kommata getrennt in eckigen Klammern [ und ] angeben, und Tupel durch die Verwendung runder Klammern ( und ):

In [ ]:
l = [ 4, 0.5, "Alice" ]
l
In [ ]:
t = ( "Bob", True )
t

Auch Listen und Tupel sind Reihen

Wie bei jeder Reihe können wir die Anzahl der Elemente bestimmen und auf einzelne Elemente über ihren Index zugreifen:

In [ ]:
len(l), len(t)
In [ ]:
l[0] # Indexierung beginnt in Python mit dem Index 0
In [ ]:
l[1]
In [ ]:
l[2]
In [ ]:
t[0]
In [ ]:
t[1]

Listen sind veränderlich

Anders als Strings und Tupel können Listen jedoch verändert werden, indem Elemente verändert, hinzugefügt oder entfernt werden:

In [ ]:
l[1] = -2.2 # Weise der Liste einen neuen Wert beim Index 1 zu
l
In [ ]:
l.append(-3) # Füge einen neuen Wert am Ende der liste hinzu
l
In [ ]:
l.pop() # Entfernt das letzte Element (bzw. das am angegebenen Index) aus der Liste und gibt es zurück

Slicing

Du kannst mit der Slicing Syntax auf Teile einer Reihe zugreifen:

slice = list[start:stop:step]

Dabei bezeichnet start den ersten Index und stop den letzten nicht mehr enthaltenen Index des Abschnitts. Mit step kannst du eine Schrittweite angeben, in der die Reihe iteriert werden soll.

Du musst nicht alle drei Argumente angeben. Per default ist dann start=0, stop=len(list) und step=1:

In [ ]:
l[:2] # Der erste Index ist per default start=0
In [ ]:
l[2:] # Der letzte Index ist per default das Ende der Reihe
In [ ]:
l[::2] # Jedes zweite Element
In [ ]:
l[::-1] # Umgekehrte Reihenfolge

Hinweis: Slicing ist ein mächtiges Werkzeug um kurzen, prägnanten Code zu schreiben und wird dir bei der Arbeit mit Numpy Arrays ab Lektion 201 - Numerik mit Numpy noch sehr häufig begegnen.

Dictionaries

Ein weiterer wichtiger Datentyp ist das Dictionary. Ein Dictionary ordnet jeweils einem Key einen Value zu und wird durch geschweifte Klammern { und } erstellt:

In [ ]:
d = { 'a':1, 'b':2, 'c':3 }
d

Auf einzelne Werte kann über ihren Key zugegriffen werden:

In [ ]:
d['a']

Dictionaries sind veränderlich wie Listen:

In [ ]:
d['d'] = 4
d

Es müssen nicht unbedingt Strings als Keys verwendet werden, und auch verschiedene Datentypen sind möglich:

In [ ]:
e = { 'some_key': 4.2, 3517: 'some_value' }
e
In [ ]:
e['some_key']
In [ ]:
e[3517]

Aufgabe 4 - Dictionaries

Schreibe ein Wörterbuch mit einigen deutschen Wörtern und ihrer Übersetzung ins Englische. Weise es der Variable d zu und verwende es dann, indem du dir einige Werte darin ausgeben lässt.

In [ ]:
### BEGIN SOLUTION
d = {
    "Wörterbuch": "dictionary"
}
### END SOLUTION
d["Wörterbuch"]
In [ ]:
from nose.tools import assert_true
try:
    d
except NameError:
    raise NameError("Es gibt keine Variable 'd'. Weise den Wert einer Variablen mit diesem Namen zu.")
assert_true(len(d) > 0, "Das Wörterbuch hat keine Einträge.")
print("Wow, {} Einträge im Wörterbuch!".format(len(d)))

Du kannst nun mit Variablen und Datentypen umgehen und den Python Interpreter rechnen lassen. Lerne in der nächsten Lektion, wie du mit Control Flow Anweisungen deine ersten Programme schreiben kannst.

Startseite | >> 102 - Control Flow