03 Datenstrukturen (Collections)

1 Listen

1.1 Zugriff auf Elemente, Teillisten

L = ['Null', 'Eins', 'Zwei', 'Drei']

# Anzahl der Elemente
print(len(L))  # 4

# Element 1
print(L[1])    # Eins

# Element 0-2
print(L[0:2])  # ['Null', 'Eins']

# Die letzten beiden Elemente
print(L[-2:])  # ['Zwei', 'Drei']

1.2 Elemente hinzufügen und löschen

L = [2, 4, 6, 8]
L.append(10)  # Der Wert 10 wird hinzugefügt
print(L)      # [2, 4, 6, 8, 10]

L.remove(4)   # Der Wert 4 wird entfernt (NICHT Element 4)
print(L)      # [2, 6, 8, 10]

del L[0:2]    # Element 0-1 werden gelöscht, kein Rückgabewert
print(L)      # [8, 10]

del L[1]      # Element 1 wird gelöscht, kein Rückgabewert
print(L)      # [8]

# Element 0 wird entfernt und zurückgegeben
print(L.pop(0))  # 8

1.3 Listen kombinieren

L1 = [1, 2, 3]
L2 = [4, 5, 6]

# Möglichkeit 1
print(L1 + L2)  # [1, 2, 3, 4, 5, 6]

L1.extend(L2)

# Möglichkeit 2
print(L1)       # [1, 2, 3, 4, 5, 6]

Prüfen, ob Wert in Liste ist:

L = ["A", "B", "C"]
x = "B"
print(x in L)  # True

1.4 List comprehensions (kompakte Erstellung von Listen)

Beispiel 1:

numbers = []
for i in range(5):
    numbers.append(i**2)
print(numbers)  # [0, 1, 4, 9, 16]

# List comprehension:
numbers = [i**2 for i in range(5)]
print(numbers)  # [0, 1, 4, 9, 16]

Beispiel 2:

L2 = []
for i in range(0, len(L)):
    if L[i] > 1:
        L2.append(L[i]*2)
print(L2)                         # [4, 6]

# List comprehension:
L = [1, 2, 3]
print([x*2 for x in L if x > 1])  # [4, 6]

List comprehension sind in einigen Fällen besser lesbar, können jedoch auch schnell unübersichtlich werden. Sie sind auch mit if-Bedingungen möglich.

Beispiel 1:

numbers = [i*-1 if i<3 else -1 for i in range(5)]
print(numbers)  # [0, -1, -2, -1, -1]

Beispiel 2:

numbers = [i+1 for i in range(5) if i != 3]
print(numbers)  # [1, 2, 3, 5]

Beim ersten Beispiel steht die if-Bedingung am Anfang, dadurch wird festgelegt, was abgespeichert wird. Beim zweiten Beispiel, bei der die if-Bedingung am Ende steht, wird festgelegt, ob überhaupt etwas abgespeichert werden soll.

1.5 Kopieren von Listen

Danger

Das Kopieren einer Liste über Variablenzuweisen (z. B. l2 = l1) führt häufig zu einem nicht gewollten Verhalten, da das Ändern von l2 auch die Änderung von l1 mit sich bringt.

Beispiel:

l1 = [1, 2]
l2 = l1
l2[0] = 3
print(l1)  # [3, 2]
print(l2)  # [3, 2]

Dies liegt daran, dass auf diese Weite l1 und l2 auf die selbe Speicheradresse verweisen:

l1 = [1, 2]
l2 = l1
print(id(l1))  # 1957190476864
print(id(l2))  # 1957190476864

Um das zu umgehen, kopiert man Listen wie folgt:

l1 = [1, 2]
l2 = l1.copy()
l2[0] = 3
print(l1)  # [1, 2]
print(l2)  # [3, 2]
Warning

Dies ist eine sog. shallow-copy. Bei mehrdimensionalen Listen funktioniert dies jedoch nicht! Es muss eine sog. deep-copy erstellt werden.

Beispiel für shallow-copy:

import copy

l1 = [[1, 2], [3, 4]]
l2 = l1.copy()  # oder l2 = copy.copy(l1)
l2[0][0] = 5
print(l1)  # [[5, 2], [3, 4]]
print(l2)  # [[5, 2], [3, 4]]
print(id(l1))        # 1957176932224
print(id(l2))        # 1957176994368
print(id(l1[0][0]))  # 1956557750640
print(id(l2[0][0]))  # 1956557750640

Beispiel für deep-copy:

import copy

l1 = [[1, 2], [3, 4]]
l2 = copy.deepcopy(l1)
l2[0][0] = 5
print(l1)            # [[1, 2], [3, 4]]
print(l2)            # [[5, 2], [3, 4]]
print(id(l1))        # 1957190472320
print(id(l2))        # 1957190477184
print(id(l1[0][0]))  # 1956557750512
print(id(l2[0][0]))  # 1956557750640

2 Arrays

Arrays sind ähnlich wie Listen, jedoch effizienter bei numerischen Operationen, insbesondere für große Datenmengen. In Python können Arrays mit dem array-Modul oder über NumPy verwendet werden.

import array

# Ein Array mit ganzen Zahlen (Typcode 'i' für Integer)
arr = array.array('i', [1, 2, 3, 4, 5])
print(arr)  # array('i', [1, 2, 3, 4, 5])

# Elementzugriff
print(arr[1])  # 2

# Element hinzufügen
arr.append(6)
print(arr)  # array('i', [1, 2, 3, 4, 5, 6])

# Element entfernen
arr.remove(3)
print(arr)  # array('i', [1, 2, 4, 5, 6])

3 Tupel

Tupel sind wie Listen, jedoch mit dem Unterschied, dass der Inhalt des Tupels nicht veränderbar ist.

t = 1, 2, 3
t = (1, 2, 3)
print(t[0])  # 1

3.1 Tuple unpacking

t = (1, 2, 3)

val1, val2, val3 = t
print(val1, val2, val3)  # 1 2 3

val1, _, val3 = t
print(val1, val3)        # 1 3

val1, *t2 = t
print(val1, t2)          # 1 [2, 3]

4 Dictionaries

Dictionaries werden benutzt, um Daten in key-value-Paaren zu speichern.

Erstellung von Dictionaries:

# Möglichkeit 1:
baujahr = {'Ford': 2019, 'Honda': 2013}
print(baujahr)  # {'Ford': 2019, 'Honda': 2013}

# Möglichkeit 2:
baujahr = dict(Ford = 2019, Honda = 2013)
print(baujahr)  # {'Ford': 2019, 'Honda': 2013}

# Möglichkeit 3: Schlüssel werden als Tupel übergeben)
baujahr = dict.fromkeys( ('Ford', 'Honda') )
baujahr['Ford'] = 2019
baujahr['Honda'] = 2013
print(baujahr)  # {'Ford': 2019, 'Honda': 2013}

Zugriff auf die Schlüssel und Werte von Dictionaries in Schleifen:

D = {'Ford': 2019, 'Honda': 2013}

print('Schlüssel des Dictionaries:')
for key in D:
    print(key)
    # Ford
    # Honda

print('\nWerte des Dictionaries:')
for value in D.values():
    print(value)
    # 2019
    # 2013

print('\nSchlüssel und Werte des Dictionaries:')
for key, value in D.items():
    print(f'{key}: {value}')
    # Ford: 2019
    # Honda: 2013

5 Sets bzw. Mengen

Siehe auch 06 Operatoren.

Operationen:

S1 = {'Banane', 'Paprika', 'Zitrone'}
S2 = {'Apfel', 'Banane', 'Birne', 'Gurke', 'Paprika'}

# Vereinigung
print(S1 | S2)  # {'Zitrone', 'Gurke', 'Birne', 'Paprika', 'Apfel', 'Banane'}

# Schnittmenge
print(S1 & S2)  # {'Paprika', 'Banane'}

# Differenz (S1 ohne S2)
print(S1 - S2)  # {'Zitrone'}

# Symmetrische Differenz (= Vereinigung ohne Schnittmenge)
print(S1 ^ S2)  # {'Apfel', 'Zitrone', 'Gurke', 'Birne'}

print('\nAlternativen:')

# Vereinigung
print(S1.union(S2)) # {'Zitrone', 'Gurke', 'Birne', 'Paprika', 'Apfel', 'Banane'}

# Schnittmenge
print(S1.intersection(S2))  # {'Paprika', 'Banane'}

# Differenz (S1 ohne S2)
print(S1.difference(S2))    # {'Zitrone'}

# Symmetrische Differenz (= Vereinigung ohne Schnittmenge)
print(S1.symmetric_difference(S2))  # {'Apfel', 'Zitrone', 'Gurke', 'Birne'}