Level 3

In diesem Level lernen wir neue Datentypen, wie list, tuple, dict, set und frozenset kennen und lernen über Objekte dieser Typen mittels einer for-Schleife zu iterieren. Wir werden die Schlüsselwörter del und for kennenlernen und auch den Schlüsselwörtern in, break, continue und else ein weiteres Mal begegnen.

Einstieg

Bisher können wir Werte in Variablen speichern, das funktioniert auch, solange wir wissen, wieviele Werte wir speichern müssen. Das muss aber nicht der Fall sein. Die Datentypen, die wir in diesem Level kennenlernen ermöglichen es meherere Werte in einem Objekt zu speichern. Jeder dieser Typen hat dabei seine Besonderheiten, die wir im Laufe des Levels lernen werden.

list

Der list Typ ist der erste, den wir uns in diesem Level anschauen möchten. Er bietet viele Möglichkeiten an, ist einfach zu bedienen, weshalb er auch häufig benutzt wird. Im Gegensatz zu allen anderen Typen, die wir bereits kennengelernt haben und auch einigen anderen, die wir noch kennenlernen, ist die Liste ein veränderlicher Typ. Das heißt wir können ein list Objekt ändern und müssen es nicht überschreiben. Die Elemente eines list Objektes können einen beliebigen Typen haben.

Erstellen einer Liste

Zuerst erstellen wir eine leere Liste, entweder benutzen wir dafür die list() Funktion oder eckige Klammern [], welche die Literale einer Liste darstellen.


In [1]:
leer = list()
leer2 = []

Es ist allerdings möglich eine Liste zu erstellen, die bereits Einträge enthält. Diese Einträge nennen wir Elemente. Für das erstellen können wir wieder die Literale nehmen oder die list() Funktion. Beim Benutzen der list() Funktion müssen wir allerdings beachten, dass diese ein Objekt in eine Liste umwandelt und das nicht mit allen Objekten geht. In dem Beispiel unten erstellen wir aus einem string eine Liste.


In [2]:
liste = [0, True, 4.2, "foo"]
liste2 = list("abracadabra")
print(liste, "Länge:", len(liste))
print(liste2, "Länge:", len(liste2))


[0, True, 4.2, 'foo'] Länge: 4
['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a'] Länge: 11

Operatoren

Für Listen gibt es ebenfalls einen + und einen * Operator:
Beim + Operator wird eine Liste erstellt, die erst alle Elemente der ersten Liste und dann alle Elemente der zweiten Liste enthält.
Beim * Operator muss der andere Wert neben der Liste ein integer sein. Es wird eine neue Liste erstellt, welche die Elemente der Liste entsprechend häufig wiederholt.


In [3]:
liste = [0, True, 4.2, "foo"]
liste2 = list("abracadabra")
print(liste + liste2)
print(liste * 2)


[0, True, 4.2, 'foo', 'a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a']
[0, True, 4.2, 'foo', 0, True, 4.2, 'foo']

Zugriff auf Elemente

Auf die Elemente einer Liste wird über deren Index zugegriffen. Dieser ist ein integer startet beim ersten Element mit 0.


In [4]:
liste = [0, True, 4.2, "foo"]
index = 0
length = len(liste)
while index < length:
    element = liste[index]
    print(index, element)
    index = index + 1


0 0
1 True
2 4.2
3 foo

Es ist allerdings auch möglich mit negativen Indices zu arbeiten. Diese starten beim letzten Element der Liste mit dem Index -1. Dadurch wird es möglich auf die letzten Elemente der Liste zuzugreifen ohne die len() Funktion benutzen zu müssen.
So können wir die Liste von eben auch rückwärts durchlaufen:


In [5]:
liste = [0, True, 4.2, "foo"]
index = -1
length = -1 * len(liste)
while index >= length:
    element = liste[index]
    print(index, element)
    index = index - 1


-1 foo
-2 4.2
-3 True
-4 0

Slicing

Es ist nicht nur möglich auf die gesamte Liste oder auf einzelne Elemente zuzugreifen. Mit slicing können wir auch auf Teile einer Liste zugreifen.

liste[start:stop:step]
  • start gibt den Index an, an dem unser Teil der Liste startet
  • stop gibt den Index an, bis zu dem unser Teil der Liste geht. Das Element mit diesem Index ist jedoch nicht enthalten.
  • step gibt die Schrittweite zwischen zwei Indices unserer Teilliste an

In [6]:
liste = [0, True, 4.2, "foo", False, "spam", "egg", 42]
print(liste[1:-1])  # von Index 1 bis Index -1
print(liste[0:6:2])  # von Index 0 bis Index 6 jedes zweite Element
print(liste[-1:0:-1])  # von Index -1 bis Index 0 jedes Element


[True, 4.2, 'foo', False, 'spam', 'egg']
[0, 4.2, False]
[42, 'egg', 'spam', False, 'foo', 4.2, True]

start, stop und step können allerdings auch weggelassen werden.

  • Wird start weggelassen startet die Teilliste mit dem ersten Element.
  • Wird stop weggelassen, endet die Teilliste mit dem letzten Element.
  • wird step weggelassen, ist die Schrittweite 1

In [7]:
liste = [0, True, 4.2, "foo", False, "spam", "egg", 42]
print(liste[2::2])  # von Index 2 bis zum Ende jedes zweite Element
print(liste[:-1:3])  # vom Start bis Index -1 jedes dritte Element
print(liste[::4])  # vom Start bis zum Ende jedes vierte Element
print(liste[1:])  # von Index 1 bis zum Ende


[4.2, False, 'egg']
[0, 'foo', 'egg']
[0, False]
[True, 4.2, 'foo', False, 'spam', 'egg', 42]

Elemente hinzufügen

Nachdem wir eine Liste erstellt haben, möchten gegebenenfalls auch Elemente hinzufügen. Dazu gibt es mehrere Möglichkeiten. Wir können mit Hilfe der list.append() Methode ein Element an unsere Liste hinten anhängen oder mit der list.insert() Methode ein Element an einem Index in unsere Liste einfügen, wobei die Elemente nach diesem Index nach hinten aufrücken.


In [8]:
liste = [0, True, 4.2, "foo", False, "spam", "egg", 42]
print(liste)
liste.append(3.14)
print(liste)


[0, True, 4.2, 'foo', False, 'spam', 'egg', 42]
[0, True, 4.2, 'foo', False, 'spam', 'egg', 42, 3.14]

In [9]:
liste = [0, True, 4.2, "foo", False, "spam", "egg", 42]
print(liste)
liste.insert(4, "test")
print(liste)


[0, True, 4.2, 'foo', False, 'spam', 'egg', 42]
[0, True, 4.2, 'foo', 'test', False, 'spam', 'egg', 42]

Elemente finden

Eventuell wollen wir wissen ob ein Element in unserer Liste enthalten ist, und wenn es in unserer Liste enthalten ist, wollen wir eventuell wissen an welcher Stelle oder wie oft.

Zuerst wollen wir lernen, wie wir mit dem Schlüsselwort in feststellen, ob ein Element in unserer Liste enthalten ist:


In [10]:
liste = [0, True, 4.2, False, "spam", "egg", 42]
print("egg:", "egg" in liste)
print("ham:", "ham" in liste)


egg: True
ham: False

Aber vorsicht:


In [11]:
liste = [0, True, 4.2, False, "spam", "egg", 42]
print("1:", 1 in liste)


1: True

Scheinbar ist der integer 1 in der Liste enthalten, obwohl keiner der Einträge auf den ersten Blick danach aussieht. Also wird ein Element unserer Liste als 1 interpretiert oder ist == 1. Um rauszufinden an welcher Stelle sich dieses Element befindet können wir die list.index() Methode benutzen. Dabei müssen wir allerdings vorsichtig sein, versuchen wir nämlich den Index eines Elementes zu finden, der nicht in der Liste enthalten ist, erhalten wir einen Fehler.


In [12]:
liste = [0, True, 4.2, False, "spam", "egg", 42]
print("1:", 1 in liste)
ind = liste.index(1)
print(liste[ind])


1: True
True

Der boolean True auf dem Index 1 wird hier also als 1 erkannt. Dieses Phänomen tritt allerdings nur mit 1 und True und 0 und False auf. Um dieses Problem zu umgehen nutzen wir im folgenden eine Liste mit anderen Elementen.


In [13]:
liste = list("abracadabra")
print(liste)
print("Erstes Auftreten von 'a':", liste.index("a"))
print("Erstes Auftreten von 'b':", liste.index("b"))
print("Erstes Auftreten von 'c':", liste.index("c"))
print("Erstes Auftreten von 'd':", liste.index("d"))


['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a']
Erstes Auftreten von 'a': 0
Erstes Auftreten von 'b': 1
Erstes Auftreten von 'c': 4
Erstes Auftreten von 'd': 6

Wie wir sehen können zeigt und list.index() lediglich das erste Auftreten eines Elementes an, auch wenn dieses Element mehrfach in der Liste auftaucht.

Um rauszufinden wie häufig ein Element in unserer Liste auftaucht können wir die list.count() Methode benutzen.


In [14]:
liste = ['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a']
print("Anzahl von 'a':", liste.count("a"))
print("Anzahl von 'b':", liste.count("b"))
print("Anzahl von 'c':", liste.count("c"))
print("Anzahl von 'd':", liste.count("d"))
print("Anzahl von 'e':", liste.count("e"))


Anzahl von 'a': 5
Anzahl von 'b': 2
Anzahl von 'c': 1
Anzahl von 'd': 1
Anzahl von 'e': 0

Dabei sehen wir auch, dass uns die list.count() Methode keinen Fehler gibt, wenn ein Element (im obigen Fall 'e') nicht in der Liste enthalten ist, sondern 0 zurück gibt.

Elemente entfernen

Wenn wir Elemente entfernen wollen, haben wir auch wieder mehrere Möglichkeiten, die sich im Wesentlichen in unserer Herangehungsweise entscheiden. Kennen wir den Index des Elementes, welches wir aus der Liste entfernen möchten, können wir das Schlüsselwort del oder die list.pop() Methode verwenden, kennen wir jedoch das Element, das wir entfernen möchten, benutzen wir die list.remove() Methode.


In [15]:
liste = ["foo", "test", 23, "spam", "egg", 42]
print(liste)
del liste[0]
print(liste)
# del liste
# print(liste)


['foo', 'test', 23, 'spam', 'egg', 42]
['test', 23, 'spam', 'egg', 42]

Wie wir sehen, können wir nicht nur einzelne Elemente einer Liste anhand ihres Indexes, sondern auch die gesamte Liste entfernen. Das Schlüsselwort del entfernt die Referenz einer Variable und somit die Variable, weshalb wir auch einen NameError erhalten, wenn wir versuchen die Variable zu benutzen, nachdem wir sie gelöscht haben.


In [16]:
liste = ["foo", "test", 23, "spam", "egg", 42]
print(liste)
element = liste.pop()
print(liste)
print("Entfernt:", element)


['foo', 'test', 23, 'spam', 'egg', 42]
['foo', 'test', 23, 'spam', 'egg']
Entfernt: 42

Oben haben wir statt des del Schlüsselwortes die list.pop() Methode benutzt. Das hat den Vorteil, dass uns die list.pop() Methode das Element, welches wir aus der Liste entfernt haben, zurück gibt. Wenn wir der list.pop() keinen Index mitgeben, entfernt sie standardmäßig das letzte Element. Wenn wir der list.pop() Methode einen Index geben, entfernt sie das Element an diesem Index aus der Liste.


In [17]:
liste = ["foo", "test", 23, "spam", "egg", 42]
print(liste)
element = liste.pop(3)
print(liste)
print("Entfernt:", element)


['foo', 'test', 23, 'spam', 'egg', 42]
['foo', 'test', 23, 'egg', 42]
Entfernt: spam

Nun wollen wir ein Element, dessen Wert wir kennen aus der Liste entfernen. Dazu benutzen wir die list.remove() Methode. Diese entfernt das erste Auftreten des Wertes, den wir ihr geben, aus der Liste.


In [18]:
liste = list("abracadabra")
print(liste)
liste.remove("a")
print(liste)
liste.remove("a")
print(liste)


['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a']
['b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a']
['b', 'r', 'c', 'a', 'd', 'a', 'b', 'r', 'a']

Verschachtelung

Da wir in einer Liste Elemente beliebigen Typs speichern können, können wir auch eine Liste als Element einer Liste speichern. Auf die innere Liste können wir dann genauso zugreifen, wie auf jedes andere Element.


In [19]:
inner_list1 = [0, 1, 2]
inner_list2 = [3, 4, 5]
outer_list = [inner_list1, inner_list2]
print(outer_list)
print("Länge outer_list:", len(outer_list))
print("outer_list[0]:", outer_list[0])
print("outer_list[1]:", outer_list[1])


[[0, 1, 2], [3, 4, 5]]
Länge outer_list: 2
outer_list[0]: [0, 1, 2]
outer_list[1]: [3, 4, 5]

Die äußere Liste enthält zwei Elemente, die in diesem Fall jeweils Listen sind.


In [20]:
inner_list1 = [0, 1, 2]
inner_list2 = [3, 4, 5]
outer_list = [inner_list1, inner_list2]
# die jeweils ersten Elemente der inneren Listen:
print("Erstes Element von:")
print("outer_list[0]:", outer_list[0][0])
print("outer_list[1]:", outer_list[1][0])


Erstes Element von:
outer_list[0]: 0
outer_list[1]: 3

Die vergessenen Methoden

Wenn wir uns mit der dir() Funktion die Methoden eines list Objektes ansehen und alle Einträge mit __ am Anfang und Ende des Namens ignorieren, stellen wir fest, dass wir noch einige Methoden nicht behandelt haben.


In [21]:
dir(list)


Out[21]:
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__delitem__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__gt__',
 '__hash__',
 '__iadd__',
 '__imul__',
 '__init__',
 '__init_subclass__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__reversed__',
 '__rmul__',
 '__setattr__',
 '__setitem__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'append',
 'clear',
 'copy',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']

Da uns die dir() Funktion eine Liste zurückgibt, können wir uns diese Methoden ausgeben lassen, indem wir die letzten 11 Elemente anzeigen:


In [22]:
dir(list)[-11:]


Out[22]:
['append',
 'clear',
 'copy',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']

list.clear()

Die list.clear() Methode können wir benutzen um alle Elemente einer Liste zu entfernen. Der Anwendungsfall ist relativ begrenzt, da wir auch einfach eine leere Liste erstellen können.


In [23]:
liste = list("abracadabra")
liste.clear()
print(liste)


[]

In [24]:
# Alternativ:
liste = list("abracadabra")
liste = list()
print(liste)


[]

list.copy()

Die list.copy() Methode kann benutzt werden um eine Kopie der Liste zu erstellen. Auch hier gibt es eine alternative Möglichkeit über Slicing, dasselbe zu erreichen.


In [25]:
liste = list("abracadabra")
liste_copy = liste.copy()
print(liste)
print(liste_copy)


['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a']
['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a']

In [26]:
# Alternativ:
liste = list("abracadabra")
liste_copy = liste[:]
print(liste)
print(liste_copy)


['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a']
['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a']

list.extend()

Die list.extend() Methode kann benutzt werden um an die bestehende Liste eine andere Liste anzuhängen.


In [27]:
liste = list("abracadabra")
liste.extend("simsala")
print(liste)


['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a', 's', 'i', 'm', 's', 'a', 'l', 'a']

In [28]:
# Alternativ:
liste = list("abracadabra")
liste = liste + list("simsala")
print(liste)


['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a', 's', 'i', 'm', 's', 'a', 'l', 'a']

list.reverse()

Mit der list.reverse() können wir eine Liste umdrehen. Wie auch die voherigen Methoden gibt es auch hier Alternativen.


In [29]:
liste = list("abracadabra")
liste.reverse()
print(liste)


['a', 'r', 'b', 'a', 'd', 'a', 'c', 'a', 'r', 'b', 'a']

In [30]:
# Alternativ:
liste = list("abracadabra")
liste = liste[::-1]
print(liste)


['a', 'r', 'b', 'a', 'd', 'a', 'c', 'a', 'r', 'b', 'a']

list.sort()

Mit list.sort() lässt sich eine Liste sortieren, solange die Elemente miteinander vergleichbar sind.


In [31]:
liste = list("abracadabra")
liste.sort()
print(liste)


['a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'd', 'r', 'r']

tuple

Ein tuple ist grob gesagt eine unveränderliche Liste. Ein Tupel hat eine Länge, Elemente können nicht entfernt oder hinzugefügt werden. Lediglich die Elemente eines Tupels lassen sich ändern, wenn sie veränderlich sind.


In [32]:
t1 = tuple("abracadabra")
t2 = (2,3,23,42)
t3 = 3,2,3
print(t1)
print(t2)
print(t3)


('a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a')
(2, 3, 23, 42)
(3, 2, 3)

Ein Tuple lässt sich über die tuple() Funktion oder über runde Klammern () definieren. Die runden Klammern können wir allerdings meistens weglassen. Der Zugriff auf die Elemente funktioniert, wie bei Listen sowohl über den Index, als auch über Slicing.


In [33]:
Tuple = tuple("abracadabra")
print(Tuple[4])
print(Tuple[0:5])


c
('a', 'b', 'r', 'a', 'c')

Wenn wir uns die Methoden von einem Tuple anschauen, stellen wir fest, dass es nur zwei "normale" Methoden gibt, die wir auch schon von der Liste kennen, nämlich tuple.count() und tuple.index(). Desweiteren können wir auf einen Tuple auch die len() Funktion und das Schlüsselwort in anwenden.


In [34]:
dir(tuple)


Out[34]:
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__getnewargs__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__rmul__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'count',
 'index']

In [35]:
Tuple = tuple("abracadabra")
print(Tuple)
print("Länge:", len(Tuple))
print("Anzahl 'a':", Tuple.count("a"))
print("Erstes 'b':", Tuple.index("b"))
print("e?", "e" in Tuple)


('a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a')
Länge: 11
Anzahl 'a': 5
Erstes 'b': 1
e? False

Wir können Tuple auch benutzen um den Wert zweier Variablen zu tauschen. Bisher würden wir dafür den Wert einer Variable in einer temporären Variable (tmp) speichern und die Werte so tauschen.


In [36]:
a = 5
b = 10
tmp = a
a = b
b = tmp
print("a:", a)
print("b:", b)


a: 10
b: 5

Durch die Verwendung von Tuplen können wir nun auf unsere temporäre Variable verzichten und den Code lesbarer gestalten:


In [37]:
a = 5
b = 10
a, b = b, a
# Alternativ: (a, b) = (b, a)
print("a:", a)
print("b:", b)


a: 10
b: 5

Strings

Jetzt da wir Listen und Tuple kennengelernt haben lohnt es sich, nochmal Strings anzuschauen, da wir auch hier auch auf einzelne Zeichen mit dem Index zugreifen können. So wie bei Listen und Tupeln, können wir auch bei Strings die str.count() und str.index() Methoden verwenden.


In [38]:
zauberwort = "abracadabra"
print(zauberwort[0])
print(zauberwort[-1])
teilwort = zauberwort[:4]
print(teilwort)


a
a
abra

In [39]:
zauberwort = "abracadabra"
zauberwort.count("a")


Out[39]:
5

In [40]:
zauberwort = "abracadabra"
print(zauberwort.index("b"))


1

In [41]:
zauberwort = "abracadabra"
print("e?", "e" in zauberwort)


e? False

dict

Ein Dictionary speichert Werte nicht anhand ihres Indexes, sondern anhand eines Schlüssels.

Erstellen eines dict

Ein leeres Dictionary kann auf zwei Arten erstellt werden:


In [42]:
leer1 = dict()
leer2 = {}

Möchten wir ein Dictionary mit Einträgen erstellen, können wir dies entweder durch die dict() Funktion erreichen, in der wir Schlüssel und Werte als Liste von Tuplen mit zwei Elementen übergeben, oder indem wir Schlüssel und Werte durch Doppelpunkte : getrennt in geschweiften Klammern {} als Literale definieren.


In [43]:
dict1 = {"name": "Max", "nachname": "Mustermann", "alter": 42}
dict2 = dict([("name", "Martha"), ("nachname", "Musterfrau"), ("alter", 23)])
print(dict1)
print(dict2)


{'name': 'Max', 'nachname': 'Mustermann', 'alter': 42}
{'name': 'Martha', 'nachname': 'Musterfrau', 'alter': 23}

Als Schlüssel sind Werte aller unveränderlichen Typen erlaubt, in einem Dictionary müssen die Schlüssel auch nicht denselben Typen haben, es ergibt sich meistens aber, dass die Schlüssel denselben Typen haben.


In [44]:
beispiel_dict = {0:"integer", True:"boolean", (0,0):"tuple", "s":"strings"}
print(beispiel_dict)


{0: 'integer', True: 'boolean', (0, 0): 'tuple', 's': 'strings'}

Zugriff

Der Zugriff auf die Elemente erfolgt dann über den entsprechenden Schlüssel:


In [45]:
Max = {"name": "Max", "nachname": "Mustermann", "alter": 42}
Martha = {"name": "Martha", "nachname": "Musterfrau", "alter": 23}
print("Alter:")
print("Max:", Max["alter"])
print("Martha:", Martha["alter"])


Alter:
Max: 42
Martha: 23

Alternativ kann für den Zugriff die dict.get() Methode benutzt werden. Diese ermöglicht es auch einen Standardwert anzugeben, wenn der Schlüssel in dem Dictionary nicht vorhanden ist.


In [46]:
Max = {"name": "Max", "nachname": "Mustermann", "alter": 42}
Martha = {"name": "Martha", "nachname": "Musterfrau"}
print("Alter:")
print("Max:", Max.get("alter", 0))
print("Martha:", Martha.get("alter", 0))


Alter:
Max: 42
Martha: 0

Den Wert zu einem Schlüssel können wir setzen indem wir einem Schlüssel einen Wert zuweisen, existiert dieser Schlüssel bereits, wird sein Wert überschrieben.


In [47]:
Max = {"name": "Max", "nachname": "Mustermann", "alter": 42}
Martha = {"name": "Martha", "nachname": "Musterfrau"}
Martha["alter"] = 23
print(Martha)


{'name': 'Martha', 'nachname': 'Musterfrau', 'alter': 23}

Natürlich kann man auch das in Schlüsselwort mit Dictionaries benutzen:


In [48]:
Martha = {"name": "Martha", "nachname": "Musterfrau"}
print("name?", "name" in Martha)
print("alter?", "alter" in Martha)


name? True
alter? False

Die len() Funktion liefert bei einem Dictionary die Anzahl an Schlüsseln wieder:


In [49]:
Martha = {"name": "Martha", "nachname": "Musterfrau"}
print("Anzahl Schlüssel:", len(Martha))


Anzahl Schlüssel: 2

items(), keys() und values()

Die drei Methoden dict.items(), dict.keys() und dict.values() sind sich relativ ähnlich, weshalb wir sie zusammen betrachten wollen.


In [50]:
dictionary = {0:"integer", True:"boolean", (0,0):"tuple", "s":"strings"}
print(dictionary.keys())  # liefert die Schlüssel als Liste
print(dictionary.values())  # liefert die Werte als Liste
print(dictionary.items())  # liefert Schlüssel und Werte als Tuple in einer Liste


dict_keys([0, True, (0, 0), 's'])
dict_values(['integer', 'boolean', 'tuple', 'strings'])
dict_items([(0, 'integer'), (True, 'boolean'), ((0, 0), 'tuple'), ('s', 'strings')])

pop()

Auch Dictionaries besitzen eine dict.pop() Methode.


In [51]:
dictionary = {0:"integer", True:"boolean", (0,0):"tuple", "s":"strings"}
value = dictionary.pop(0)
print(dictionary)


{True: 'boolean', (0, 0): 'tuple', 's': 'strings'}

Wie wir sehen funktioniert die dict.pop() Methode ähnlich, wie bei den Listen. Der Wert mit dem angegebenen Schlüssel wird zurückgegeben und aus dem Dictionary entfernt.

Die for-Schleife

Die for-Schleife kann benutzt werden um über verschiedene Objekte zu iterieren. Dabei ist die Syntax einer for-Schleife die folgende:

for variable in objekt:
    Befehle
  • objekt ist dabei das Objekt, über das wir iterieren.
  • variable enthält jeweils ein Element aus dem Objekt.

Wir kennen bereits Listen, Tuple, Dictionaries und Strings, über jeden dieser Typen können wir iterieren.


In [52]:
# Iteration über einen string:
zauberwort = "abracadabra"
for zeichen in zauberwort:
    print(zeichen)


a
b
r
a
c
a
d
a
b
r
a

In [53]:
# Iteration über eine Liste:
liste = [0, True, "foo", 42]
for element in liste:
    print(element)


0
True
foo
42

In [54]:
# Iteration über einen Tuple:
Tuple = (1,2,3)
for zahl in Tuple:
    print(zahl)


1
2
3

In [55]:
# Iteration über ein Dictionary:
Max = {"name": "Max", "nachname": "Mustermann", "alter": 42}
for attribut in Max:
    print(attribut, ":", Max[attribut])


name : Max
nachname : Mustermann
alter : 42

In [56]:
# Alternativ:
Max = {"name": "Max", "nachname": "Mustermann", "alter": 42}
for attribut, wert in Max.items():
    print(attribut, ":", wert)


name : Max
nachname : Mustermann
alter : 42

range()

Die range() Funktion ist in vielerlei Hinsicht praktisch. Sie ermöglicht es uns auf einfache, gut lesbare Art und Weise Zahlenfolgen zu erzeugen. Warum das so praktisch ist werden wir gleich sehen.

range(stop)
range(start, stop[, step])

Wir können range() entweder nur mit einem stop Wert aufrufen (dieser muss ein integer sein), oder mit einem start, einem stop und einen optionalen step Wert. Bei beiden Varianten erhalten wir ein range Objekt. Diese verhalten sich ähnlich wie die Werte beim Slicing. Geben wir keinen Wert für start an startet unser range Objekt bei 0, geben wir keinen Wert für step an, ist die Schrittweite 1.


In [57]:
# alle Zahlen von 0 bis 10:
r = range(10)
print(list(r))


[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [58]:
# jede zweite Zahl von 2 bis 42:
r = range(2, 42, 2)
print(list(r))


[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40]

Genauso, wie beim Slicing können die Werte auch negativ sein.


In [59]:
# von 0 bis -100 jede zweite Zahl:
r = range(0, -100, -2)
print(list(r))


[0, -2, -4, -6, -8, -10, -12, -14, -16, -18, -20, -22, -24, -26, -28, -30, -32, -34, -36, -38, -40, -42, -44, -46, -48, -50, -52, -54, -56, -58, -60, -62, -64, -66, -68, -70, -72, -74, -76, -78, -80, -82, -84, -86, -88, -90, -92, -94, -96, -98]

Ein range Objekt kann auch benutzt werden um sehr große Zahlenreihen zu erzeugen, da die Zahlen erst berechnet werden, wenn sie benötigt werden.


In [60]:
r = range(10000000000000000)
print(r)


range(0, 10000000000000000)

Dadurch, dass wir über ein range Objekt iterieren können, können wir range() gut in einer for-Schleife benutzen.


In [61]:
for i in range(10):
    print(i)


0
1
2
3
4
5
6
7
8
9

break, continue und else

Die Schlüsselwörter break, continue und else können wir innerhalb einer for-Schleife genauso benutzen, wie in einer while-Schleife.


In [62]:
zauberwort = "abracadabra#test"
neuer_zauber = ""
for zeichen in zauberwort:
    if zeichen == "#":
        break
    elif zeichen == "a":
        continue
    else:
        neuer_zauber += zeichen
print(neuer_zauber)


brcdbr

In [63]:
string = "Das ist ein Teststring."
for zeichen in string:
    if zeichen == "Y":
        break
else:
    print("Kein 'Y' gefunden.")


Kein 'Y' gefunden.

for-Schleifen können verschachtelt werden, was wir benutzen können um über ein verschachteltes Objekt zu iterieren.


In [3]:
table = [
    [
        "test",
        "foo",
        "bar"
    ],
    [
        "ham",
        "spam",
        "egg"
    ]
]
for row in table:
    for entry in row:
        print(entry)


test
foo
bar
ham
spam
egg

sets

Sets sind Mengen im mathematischen Sinn. Das bedeutet ein Element kann entweder in einer Menge enthalten sein, oder eben nicht.

Erstellen eines set

Ein Set kann entweder über die set() Funktion aus einem anderen Objekt erzeugt werden, oder über geschweifte Klammern {} welche die Literale eines Sets bilden.


In [64]:
Set = set()
print(Set)


set()

In [5]:
Set = {2,3,5,7}
print(Set)


{2, 3, 5, 7}

in und len()


In [7]:
some_primes = {2, 3, 5, 7, 11, 13}
print(12 in some_primes)


False

In [8]:
some_primes = {2, 3, 5, 7, 11, 13}
print(len(some_primes))


6

Elemente hinzufügen

Nach dem wir eine Menge erstellt haben, können wir mit der set.add() Methode Elemente hinzufügen.


In [1]:
some_primes = {2, 3, 5, 7, 11, 13}
some_primes.add(17)
print(some_primes)


{2, 3, 5, 7, 11, 13, 17}

Um nicht nur einzelne Elemente, sondern mehrere Elemente an eine Menge anzuhängen, können wir die set.update() Methode benutzen.


In [4]:
some_primes = {2, 3, 5, 7, 11, 13}
more_primes = [17, 19, 23]
some_primes.update(more_primes)
print(some_primes)


{2, 3, 5, 7, 11, 13, 17, 19, 23}

Elemente entfernen

Um Elemente zu entfernen gibt es zwei Möglichkeiten. Die set.pop() Methode entfernt ein Element aus der Menge und gibt es dabei zurück. Die set.remove() Methode kann dafür benutzt werden, um Elemente anhand ihres Wertes aus der Menge zu entfernen.


In [2]:
Set = {23, "foo", 42, "test", (1,2)}
element = Set.pop()
print(element)
print(Set)


(1, 2)
{'test', 42, 'foo', 23}

In [3]:
Set = {23, "foo", 42, "test", (1,2)}
Set.remove("foo")
print(Set)


{(1, 2), 'test', 42, 23}

Mengenoperationen

Set-Objekte bieten Mengenoperationen an, die auch aus der Mathematik bekannt sind. Diese sind die Schnittmenge, die Vereinigungsmenge und die Differenzmenge.

Die Schnittmenge enthält alle Elemente, die in beiden Mengen enthalten sind.


In [10]:
# Schnittmenge zweier Mengen:
set1 = {1, 3, 4, 5, 2}
set2 = {5, 8, 1, 3, 7, 9}
schnittmenge = set1 & set2
print(schnittmenge)


{1, 3, 5}

Alternativ können wir auch die set.intersection() Methode benutzen.


In [11]:
# Schnittmenge zweier Mengen:
set1 = {1, 3, 4, 5, 2}
set2 = {5, 8, 1, 3, 7, 9}
schnittmenge = set1.intersection(set2)
print(schnittmenge)


{1, 3, 5}

Die Vereinigungsmenge enthält alle Elemente, die in einer der Mengen enthalten sind.


In [13]:
# Vereinigungsmenge zweier Mengen:
set1 = {1, 3, 4, 5, 2}
set2 = {5, 8, 1, 3, 7, 9}
vereinigung = set1 | set2
print(vereinigung)


{1, 2, 3, 4, 5, 7, 8, 9}

Alternativ können wir auch die set.union() Methode benutzen.


In [15]:
# Vereinigungsmenge zweier Mengen:
set1 = {1, 3, 4, 5, 2}
set2 = {5, 8, 1, 3, 7, 9}
vereinigung = set1.union(set2)
print(vereinigung)


{1, 2, 3, 4, 5, 7, 8, 9}

Die Differenzmenge einer Menge S1 mit einer Menge S2 enthält alle Elemente, die in der Menge S1 aber nicht in der Menge S2 sind.


In [16]:
s1 = {1, 3, 4, 5, 2}
s2 = {4, 5}
differenz = s1 - s2
print(differenz)


{1, 2, 3}

Alternativ können wir auch die set.difference() Methode benutzen.


In [17]:
s1 = {1, 3, 4, 5, 2}
s2 = {4, 5}
differenz = s1.difference(s2)
print(differenz)


{1, 2, 3}

Es gibt auch noch die symmetrische Differenzmenge zweier Mengen. Diese enthält alle Elemente, die in einer der beiden Mengen, aber nicht in beiden Mengen enthalten sind.


In [19]:
s1 = {1, 3, 4, 5, 2}
s2 = {4, 5, 6}
sym_differenz = s1 ^ s2
print(sym_differenz)


{1, 2, 3, 6}

Alternativ können wir für die symmetrische Differenz auch die set.symmetric_difference() Methode benutzen.


In [21]:
s1 = {1, 3, 4, 5, 2}
s2 = {4, 5, 6}
sym_differenz = s1.symmetric_difference(s2)
print(sym_differenz)


{1, 2, 3, 6}

Mit der set.isdisjoint() Methode können wir testen ob zwei Mengen disjunkt sind. Zwei Mengen sind disjunkt, wenn ihre Schnittmenge leer ist.


In [28]:
s1 = {1, 3, 4, 5, 2}
s2 = {4, 5, 6}
s3 = {7, 8, 2}
print(s1.isdisjoint(s2))
print(s2.isdisjoint(s3))


False
True

Mit der set.issubset() und der set.issuperset() Methode können wir feststellen, ob eine Menge eine Teilmenge, beziehungsweise eine Obermenge einer anderen Menge ist. Eine Menge s1 ist Teilmenge einer Menge s2, wenn alle Elemente von s1 in der Menge s2 enthalten sind. s2 ist dann die Obermenge von s1.


In [32]:
s1 = {1, 2, 3, 4, 5}
s2 = {1, 2}
print("Ist s2 eine Teilmenge von s1:")
print(s2.issubset(s1))
print("Ist s1 eine Obermenge von s2:")
print(s1.issuperset(s2))


Ist s2 eine Teilmenge von s1:
True
Ist s1 eine Obermenge von s2:
True

Statt der set.issubset() Methode können wir auch den <= Operator benutzen, statt der set.issuperset() Methode können wir auch den >= Operator benutzen.

Den > Operator können wir benutzen um zu ermitteln, ob eine Menge s1 eine echte Obermenge von einer Menge s2 ist. Dies ist der Fall, wenn s1 eine Obermenge von s2 und nicht die gleiche Menge ist.

Den < Operator können wir benutzen um zu ermitteln, ob eine Menge s1 eine echte Teilmenge einer Menge s2 ist. Dies ist der Fall, wenn s1 eine Teilmenge von s2 ist und nicht die gleiche Menge ist.


In [33]:
s1 = {1, 2, 3, 4}
s2 = {1, 2}
print(s2 < s1)
print(s1 > s2)


True
True

frozenset

Ein frozenset ist eine 'eingefrorene' Menge, das heißt sie ist unveränderlich. Die grundsätzlichen, oben besprochenen Methoden sind jedoch auch für ein frozenset Objekt vorhanden.