= [23, "Hallo", "test", 1.44, True] x
Listen erstellen
Eine Liste (list
) ist wie ein String (str
) ein Sequenzdatentyp. Im Gegensatz zu einem String kann eine Liste aber Elemente mit unterschiedlichen Datentypen enthalten, z.B. Strings, Zahlen, weitere Listen, und so weiter. Eine Liste erstellt man mit eckigen Klammern, innerhalb derer die einzelnen Elemente durch Kommas getrennt angegeben werden:
= [1, "1", [1, 2, 3], ["test", False, [True, True, 2, 4]]] y
Indizieren und Slicen
Der Zugriff auf einzelne (bzw. mehrere) Elemente funktioniert genau wie bei Strings durch Indizierung (bzw. Slicen) mit eckigen Klammern.
0] # erstes Element x[
23
-2] # vorletztes Element x[
1.44
1:4] # drei Elemente x[
['Hallo', 'test', 1.44]
-1] # ganze Liste in umgekehrter Reihenfolge x[::
[True, 1.44, 'test', 'Hallo', 23]
Arbeiten mit Listen
Länge
Wie bei Strings gibt die Funktion len
die Länge der Liste (also die Anzahl der Elemente in der Liste) zurück.
len(x)
5
len(y)
4
Selbstverständlich ist eine leere Liste auch eine Liste, nur eben mit der Länge 0:
= []
z len(z)
0
type(z)
list
Elemente verändern
Nachdem Listen mutable sind, kann man einzelne Elemente auch nach der Erstellung der Liste ändern.
x
[23, 'Hallo', 'test', 1.44, True]
1] = 111111
x[ x
[23, 111111, 'test', 1.44, True]
0] = None
x[ x
[None, 111111, 'test', 1.44, True]
Operatoren +
und *
Zwei Listen kann man mit dem +
-Operator zu einer neuen Liste zusammenfügen:
1, 2, "drei"] + ["vier", 5, 6.0] [
[1, 2, 'drei', 'vier', 5, 6.0]
Der *
-Operator vervielfältigt eine Liste:
1, 2.0, "drei"] * 3 [
[1, 2.0, 'drei', 1, 2.0, 'drei', 1, 2.0, 'drei']
Elemente zu Listen hinzufügen
Mit der Methode append
kann man neue Elemente am Ende der Liste hinzufügen.
x
[None, 111111, 'test', 1.44, True]
13)
x.append( x
[None, 111111, 'test', 1.44, True, 13]
Im Gegensatz zu Strings wird hier die Liste direkt (in place) verändert; eine erneute Zuweisung zu einem Namen ist nicht notwendig bzw. führt nicht zum gewünschten Ergebnis wie in folgendem Beispiel ersichtlich:
= x.append(25) a
print(a) # Listen-Methoden geben None zurück, da Sie die Liste direkt ändern
None
# geänderte Liste x
[None, 111111, 'test', 1.44, True, 13, 25]
Listen-Methoden verändern die Liste direkt (in-place) und geben nichts (None
) zurück. Im Gegensatz dazu können String-Methoden den String nicht verändern und geben daher einen neuen String zurück.
Möchte man gleich mehrere Elemente hinzufügen, kann man die Methode extend
benutzen:
99, "HH", "zz"])
x.extend([ x
[None, 111111, 'test', 1.44, True, 13, 25, 99, 'HH', 'zz']
Versuchen Sie anhand dieses Beispiels den Unterschied zwischen append
und extend
zu erklären!
Elemente aus Listen entfernen
Um Elemente an bestimmten Indizes aus der Liste zu entfernen verwendet man den del
-Befehl.
= ["A", "b", 3, 4, "fünf"]
x del x[1] # löscht das Element mit dem Index 1
x
['A', 3, 4, 'fünf']
Alternativ kann man auch die Methode pop
zum Löschen eines Elementes an einem bestimmten Index verwenden. Diese gibt das entfernte Element auch zurück (was del
nicht tut).
= ["A", "b", 3, 4, "fünf"]
x 1) x.pop(
'b'
x
['A', 3, 4, 'fünf']
Die Methode remove
entfernt das erste Element aus der Liste, welches dem gesuchten Wert entspricht. Hier gibt man also nicht den zu entfernenden Index an, sondern den zu löschenden Wert.
= ["A", "b", 31, 41, "fünf"]
x 31)
x.remove( x
['A', 'b', 41, 'fünf']
Listen sortieren
Wenn eine Liste sortierbare Elemente enthält (z.B. lauter Zahlen), kann man sie mit der Methode sort
sortieren.
= [6, 9, 23, 1, -78, 44]
h
h.sort() h
[-78, 1, 6, 9, 23, 44]
Was passiert, wenn man eine Liste mit nicht sortierbaren Elementen sortieren möchte (z.B. die Liste x
aus dem vorigen Beispiel)?
Listen umdrehen
Eine Liste kann man wie einen String mit folgendem Slice umdrehen (die ursprüngliche Liste ändert sich dabei aber nicht):
-1] h[::
[44, 23, 9, 6, 1, -78]
Es gibt aber noch eine zweite Möglichkeit, welche die Liste direkt (in-place) verändert:
h.reverse() h
[44, 23, 9, 6, 1, -78]
Listen iterieren
Mit dem in
-Operator kann man abfragen, ob ein bestimmtes Element in einer Liste enthalten ist.
2 in h
False
-78 in h
True
Eine Liste ist wie jeder Sequenzdatentyp iterierbar, d.h. man kann mit einer for
-Schleife über die einzelnen Elemente iterieren:
for k in [2, "fünf", 3.14, "sieben"]:
print(k)
2
fünf
3.14
sieben
Tupel
Tupel verhalten sich wie Listen, sind aber immutable. Das bedeutet, dass man einzelne Elemente nicht verändern kann. Tupel erstellt man wie Listen, nur lässt man die eckigen Klammern weg (man benötigt auch keine runden Klammern, obwohl diese manchmal in Kombination mit anderen Befehlen syntaktisch notwendig sind, z.B. wenn man ein Tupel als Argument übergeben möchte).
= "A", "b", 3, 4, "fünf"
t t
('A', 'b', 3, 4, 'fünf')
1] t[
'b'
1] = "c" # Fehler! t[
TypeError: 'tuple' object does not support item assignment
List Comprehensions
List Comprehensions sind eine alternative Möglichkeit, mit der man elegant Listen erstellen kann. List Comprehensions sind im Prinzip Schleifen, die man aber syntaktisch kompakter darstellen kann (streng genommen sind List Comprehension eigentlich gar nicht notwendig, weil man damit nichts machen kann was anders nicht auch möglich wäre).
Nehmen wir als Beispiel eine Liste der Quadratzahlen von 0 bis 9. Mit einer normalen Schleife würde man diese Liste so erstellen:
= [] # wir beginnen mit leerer Liste
squares for x in range(10):
**2) # Liste wird befüllt
squares.append(x
squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Dasselbe Ergebnis kann mit einer List Comprehension viel kürzer geschrieben werden:
= [x**2 for x in range(10)]
squares squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Die Zutaten einer List Comprehension sind:
- Zwei umschließende eckige Klammern (die ja eine Liste definieren)
- Ein Ausdruck
- Eine
for
-Anweisung (die über ein Objekt iteriert) - Optional eine
if
-Bedingung - Optional weitere
for
-Anweisungen
Ein relativ komplexes Beispiel könnte wie folgt aussehen:
- 1, y - 2) for x in [1, 2, 3] for y in [3, 1, 4] if x != y] [(x
[(0, 1), (0, 2), (1, 1), (1, -1), (1, 2), (2, -1), (2, 2)]
Als Übung können Sie versuchen, diese List Comprehension mit normalen Schleifen anzuschreiben!
Weitere Beispiele veranschaulichen, dass List Comprehensions eine Operation auf alle Elemente einer Liste anwenden oder bestimmte Elemente herausfiltern können:
= [-4, -2, 0, 2, 4] vec
* 2 for x in vec] # neue Liste mit verdoppelten Einträgen [x
[-8, -4, 0, 4, 8]
for x in vec if x >= 0] # negative Einträge herausfiltern [x
[0, 2, 4]
abs(x) for x in vec] # eine Funktion auf alle Elemente separat anwenden [
[4, 2, 0, 2, 4]
In Python ist es mit Listen also nicht einfach möglich, elementweise Berechnungen durchzuführen.
= [4, -3, 7, 81, 11]
x * 2 x
[4, -3, 7, 81, 11, 4, -3, 7, 81, 11]
Hier werden also die einzelnen Elemente nicht mit 2 multipliziert, sondern die Liste wird “verzweifacht”. Immer dann, wenn man eine Operation elementweise anwenden möchte, muss man daher eine List Comprehension (oder die entsprechende Schleife) verwenden.
Für numerische Anwendungen ist das aber denkbar unpraktisch. Wir werden in einer der folgenden Einheiten kennenlernen, wie man Python dennoch für numerische Berechnungen verwenden kann (nämlich dank eines neuen Datentyps namens NumPy Array, welches vom Zusatzpaket NumPy zur Verfügung gestellt wird).
Noch ein Beispiel:
= [' perSon', ' WoMaN ', 'MAN ', 'CAMERA', 'tv'] x
+ "!" for item in x] [item.strip().upper()
['PERSON!', 'WOMAN!', 'MAN!', 'CAMERA!', 'TV!']
In der Praxis verwendet man List Comprehensions so lange diese noch relativ einfach und übersichtlich sind. Hat man aber mehrere geschachtelte Schleifen und Bedingungen, verwendet man besser explizite Schleifen, da diese dann besser lesbar sind.
Dictionaries
Der Datentyp Dictionary ist ein sogenannter Mapping-Datentyp. Man kann sich ein Dictionary wie ein Sprachwörterbuch vorstellen (daher auch der Name). Wenn man die Übersetzung zu einem bestimmten Wort wissen möchte, schlägt man unter dem gesuchten Wort (hier Key genannt) nach und findet dort die Übersetzung (hier als Value bezeichnet). In Python definiert man ein dict
mit geschwungenen Klammern und trennt die Einträge wie bei Listen mit Kommas. Jeder Eintrag besteht aus einem Key und einem Value, welche durch einen Doppelpunkt voneinander getrennt sind.
Folgendes Beispiel zeigt ein dict
mit drei Einträgen:
= {"Haus": "house", "Schlange": "snake", "Katze": "cat"} d
Alternativ kann man auch die dict
-Funktion benutzen. Mit Keyword-Argumenten kann man so das Dictionary initialisieren:
= dict(Haus="house", Schlange="snake", Katze="cat") d
Man beachte, dass die Keyword-Argumente Argumente sind und dementsprechend ohne Anführungszeichen geschrieben werden müssen. Diese werden dann aber in Strings umgewandelt und als Keys im Dictionary verwendet.
Einzelne Elemente kann man wieder mit Indizierung herausgreifen – anstelle eines numerischen Index (wie bei Listen) gibt man aber nun den jeweiligen Key als Index an:
"Haus"] d[
'house'
"Schlange"] d[
'snake'
Ein Dictionary ist also gewissermaßen eine verallgemeinerte Liste. Ein wichtiger Unterschied zu Listen ist, dass die Reihenfolge der Einträge in Dictionaries keine Rolle spielt. D.h. man kann bei einem Dictionary nicht vom ersten, zweiten, dritten Element usw. sprechen – bei Listen hingegen schon.
Genau wie in Listen kann man in Dictionaries Elemente mit unterschiedlichen Datentypen speichern. Eine Einschränkung gibt es aber für die Keys: diese müssen immutable sein (daher kann man z.B. keine Listen als Keys verwenden). Neue Elemente fügt man einfach durch Angabe von Key und Value zu einem bestehenden Dictionary hinzu.
d
{'Haus': 'house', 'Schlange': 'snake', 'Katze': 'cat'}
23] = "tt"
d[1] = 3.14
d["L"] = [1, 2, 3]
d[ d
{'Haus': 'house',
'Schlange': 'snake',
'Katze': 'cat',
23: 'tt',
1: 3.14,
'L': [1, 2, 3]}
Gibt man einen Key an, der im Wörterbuch nicht existiert, erhält man eine Fehlermeldung.
0] # Fehler! d[
KeyError: 0
Arbeiten mit Dictionaries
Die Länge eines Dictionaries, also die Anzahl der Einträge, bestimmt man mit der Funktion len
:
len(d)
6
Die Keys bekommt man mit der Methode keys
, die Values mit der Methode values
:
d.keys()
dict_keys(['Haus', 'Schlange', 'Katze', 23, 1, 'L'])
d.values()
dict_values(['house', 'snake', 'cat', 'tt', 3.14, [1, 2, 3]])
Ob ein Wert als Key vorkommt, kann man mit in
überprüfen:
"Katze" in d
True
"cat" in d
False
Wenn man wissen möchte, ob ein Wert als Value vorkommt, verwendet man die values
-Methode:
"cat" in d.values()
True
Selbstverständlich kann man über ein Dictionary auch iterieren – in diesem Fall wird über die Keys iteriert:
for k in d:
print(k)
Haus
Schlange
Katze
23
1
L
Auf die entsprechenden Values greift man dann durch Indizieren zu:
for k in d:
print(k, ":", d[k])
Haus : house
Schlange : snake
Katze : cat
23 : tt
1 : 3.14
L : [1, 2, 3]
Eleganter funktioniert das mit der Methode items
. Diese erzeugt eine Liste von Tupeln, welche die Key/Value-Paare enthalten:
d.items()
dict_items([('Haus', 'house'), ('Schlange', 'snake'), ('Katze', 'cat'), (23, 'tt'), (1, 3.14), ('L', [1, 2, 3])])
Damit kann man in einer Schleife sowohl auf die Keys als auch auf die Values zugreifen.
for k, v in d.items():
print(k, ":", v)
Haus : house
Schlange : snake
Katze : cat
23 : tt
1 : 3.14
L : [1, 2, 3]
Die gleichzeitige Zuweisung von Werten an die Namen k
und v
bezeichnet man in Python als Unpacking – nachdem d.items()
jeweils ein Tupel bestehend aus zwei Elementen erzeugt, kann man diese zwei Elemente direkt zwei Namen zuweisen.
Ein weiteres Beispiel für Tuple Unpacking ist das Vertauschen von zwei Werten. Zunächst kann man damit zwei (oder mehr) Namen gleichzeitig zuweisen:
= 15, 23 a, b
a
15
b
23
Da Python immer zuerst die rechte Seite einer Zuweisung auswertert, kann man mit diesem Muster auch zwei Werte vertauschen:
= b, a a, b
a
23
b
15
Möchte man den Fehler beim Zugriff auf einen nicht existierenden Key vermeiden, kann man stattdessen die Methode get
verwenden. Diese Methode hat zwei Parameter, nämlich einen Key und einen Standardwert, der zurückgegeben wird falls der angegebene Key im Dictionary nicht existiert:
d
{'Haus': 'house',
'Schlange': 'snake',
'Katze': 'cat',
23: 'tt',
1: 3.14,
'L': [1, 2, 3]}
"psy"] # Fehler, Key "psy" existiert nicht d[
KeyError: 'psy'
"psy", 0) # Key "psy" exisitiert nicht, also wird 0 zurückgegeben d.get(
0
"Schlange", "Tier") # Key "Schlange" existiert d.get(
'snake'
"snake", "Schlange") # Key "snake" existiert nicht d.get(
'Schlange'
Zu beachten ist, dass in den Fällen, wo Standardwerte zurückgegeben werden, diese Einträge nicht automatisch zum Dictionary hinzugefügt werden:
d
{'Haus': 'house',
'Schlange': 'snake',
'Katze': 'cat',
23: 'tt',
1: 3.14,
'L': [1, 2, 3]}
Möchte man diese neuen Einträge gleich dem Dictionary hinzufügen, verwendet man die Methode setdefault
:
"X", 42) # Key "X" existiert nicht d.setdefault(
42
# jetzt gibt es den Key "X" d
{'Haus': 'house',
'Schlange': 'snake',
'Katze': 'cat',
23: 'tt',
1: 3.14,
'L': [1, 2, 3],
'X': 42}
"X", 100) # Key "X" existiert bereits d.setdefault(
42
d
{'Haus': 'house',
'Schlange': 'snake',
'Katze': 'cat',
23: 'tt',
1: 3.14,
'L': [1, 2, 3],
'X': 42}
Übungen
Übung 1
Schreiben Sie eine Funktion histogram
, welche eine Liste mit Zahlen entgegennehmen und diese als vereinfachtes Histogramm am Bildschirm darstellen soll. Dieses Histogramm soll für jeden Wert eine Zeile ausgeben mit der entsprechenden Anzahl an Zeichen. Das Standardzeichen soll ein Stern (*
) sein, aber dieses Zeichen soll mit einem Parameter namens char
anpassbar sein. Beispiele für mögliche Funktionsaufrufe und deren Ergebnisse lauten:
>>> histogram([1, 8, 5, 17, 14, 9, 2])
*
********
*****
*****************
**************
*********
**
>>> histogram([1, 8, 5, 17, 2], char="-")
-
--------
-----
-----------------
--
Diese Funktion liefert keinen Wert zurück, sondern gibt das Histogramm (mit Hilfe der print
-Funktion) am Bildschirm aus.
Übung 2
Schreiben Sie eine Funktion sum_of_squares
, welche eine Liste mit Zahlen als Parameter entgegennimmt und die Quadratsumme dieser Zahlen (also eine einzige Zahl) zurückgibt.
Sie könnten in der Funktion z.B. zuerst eine Liste mit den quadrierten Zahlen erstellen, deren Elemente mit der Funktion sum
addieren und das Ergebnis zurückgeben.
Übung 3
Erstellen Sie eine Liste mit den ganzen Zahlen von 1 bis 25 und weisen Sie dieser Liste den Namen numbers
zu. Erstellen Sie dann fünf neue Listen, welche folgende Zahlen beinhalten (basierend auf numbers
, die neuen Listen sollen wie angegeben benannt werden):
- Die Quadratzahlen
squares
. - Die geraden Zahlen
evens
. - Die ungeraden Zahlen
odds
. - Die Wurzeln
roots
. - Die natürlichen Logarithmen
logs
.
Verwenden Sie zur Erstellung der neuen Listen jeweils eine geeignete List Comprehension.
Für die letzten beiden Listen verwenden Sie am besten Funktionen aus dem Modul math
.
Übung 4
Schreiben Sie folgende List Comprehension um, indem Sie zwei geschachtelte for
-Schleifen verwenden:
= [x**2 - y for x in range(7) for y in [3, 1, 5] if x != y] z
Übung 5
Erstellen Sie ein Dictionary a
, welches drei Einträge hat und Übersetzungen der Wörter “eins”, “zwei” und “drei” auf Englisch beinhalten soll. Wie können Sie die Übersetzung von “zwei” dann aus a
anzeigen lassen?
Übung 6
Fügen Sie dem Dictionary a
aus der vorigen Übung einen neuen Eintrag (“vier” – “four”) hinzu und geben Sie das gesamte Dictionary am Bildschirm aus.
Übung 7
Was passiert, wenn Sie im Dictionary a
auf den nicht existierenden Key "zehn"
zugreifen wollen? Welche zwei Alternativen gibt es, um für nicht existierende Keys einen Standardwert (z.B. "undefiniert"
) zurückzugeben (und daher die Fehlermeldung zu vermeiden)? Was ist der Unterschied zwischen diesen beiden Möglichkeiten? Geben Sie in Ihrer Antwort auch den konkreten Code für die drei Zugriffsmöglichkeiten auf das Element "zehn"
von a
an!
Übung 8
In der letzten Einheit haben wir eine Funktion namens find
definiert, welche sich wie die String-Methode str.find
verhält. Allerdings findet diese Funktion (und auch die Methode) nur das erste Vorkommen des gesuchten Zeichens, z.B. "Werkstatttreppe".find("t")
gibt 5
zurück (die Position des ersten t
). Es wäre praktisch, wenn die Indizes aller gesuchten Zeichen in einer Liste zurückgegeben würden, also in diesem Beispiel [5, 7, 8, 9]
. Falls das Zeichen gar nicht vorkommen sollte, soll eine leere Liste zurückgegeben werden. Schreiben Sie eine Funktion find
, die sich entsprechend verhält!