Link Search Menu Expand Document

Listen und Tuple

Listen

Programme bearbeiten häufig große Mengen Daten identischer Struktur. Am Anfang wurde schon das Beispiel gegeben, die Durchschnittsnote aller Teilnehmer der Veranstaltung "Python-Programmierung" zu bestimmen. Hierzu muss man eine Reihe von Noten durchlaufen und das arithmetische Mittel bestimmen. Die einzelnen Datenpunkte sind alle vom selben Typ und es wäre sehr mühselig, wenn man jede Note in einer einzelnen Variable speichern würde:

n1 = 1.3
n2 = 2.3
n3 = 1.7
n4 = 2.7
n5 = 4.0
n6 = 1.3
pypnote = (n1 + n2 + n3 + n4 + n5 + n6) / 6

Käme eine weitere Teilnehmerin dazu, müsste man eine weitere Variable (n7) einführen und die Formel für den Durchschnitt an zwei Stellen ändern. Das kann nicht sinnvoll sein.

Deswegen gibt es in jeder Programmiersprache eine Möglichkeit gleichartige Daten zusammenzufassen und dann "auf einen Rutsch" zu verarbeiten. In Java oder C/C++ heißen diese Datenstrukturen Arrays in Python spricht man von Listen.

  • Oft möchte man größere Mengen von Daten gleichartig bearbeiten
  • Listen (lists) speichern mehrere Werte geordnet
  • Daten können von unterschiedlichen Typen sein
  • Zugriff erfolgt über [] mit Index
my_list = [ 2, 3, 5, 7, 11, 13, 'Hugo' ]

my_list[0] # -> 2
my_list[1] # -> 3

Eine Liste kann beliebig viele Elemente enthalten und die Elemente können von unterschiedlichen Typen sein. In der Praxis wird man aber normalerweise darauf achten, dass nur Elemente eines Typs in der Liste vorkommen, weil sonst die Verarbeitung zu kompliziert wird.

Bei einer Liste hat man dann eine Variable (my_list im Beispiel) über die man auf alle Elemente zugreifen kann. Das einzelne Element wählt man über seinen Index aus, den man in eckigen Klammern ([]) nach dem Namen der Variable angibt, z. B. my_list[3] für das vierte Element.

Wieso liefert my_list[3] das 4. und nicht das 3. Element?

  • Index beginnt bei 0
  • Negative Indices zählen von hinten
my_list = [ 1, 2, 3, 4, 5 ]

my_list[0] # -> 1
my_list[1] # -> 2

my_list[-1] # -> 5
my_list[-2] # -> 4

my_list[5] # IndexError: list index out of range

In fast allen Programmiersprachen (mit Ausnahme von Lua) wird bei einem Array bzw. einer Liste immer bei 0 mit dem Zählen begonnen. D. h. das erste Element hat den Index 0, das zweite den Index 1 usw.

Verwendet man einen Index, der außerhalb der möglichen Indices für die vorhandenen Elemente liegt, dann bricht das Programm mit einem Fehler (IndexError) ab.

Python bietet die Möglichkeit, die Elemente auch von hinten zu adressieren, indem man negative Indices verwendet. Hierbei ist -1 das letzte Element, -2 das vorletzte usw. Haben wir also ein Array a mit drei Elementen, dann gilt a[0] = a[-3], a[1] = a[-2] und a[2] = a[-1] oder ganz allgemein für ein Array mit n Elementen: a[i] = a[-(n - i)].

Eine Liste kann jederzeit verändert werden: Man kann Elemente hinzufügen oder vorhandene Elemente ersetzen.

  • Listen sind veränderlich
  • Zuweisung über den Index
# Element ersetzen
my_list = [0, 23, 42]

my_list[0] = 7
print(my_list) #-> [7, 23, 42]

# Element anfügen
my_list.append(128)
print(my_list) #-> [7, 23, 42, 128]

# Elemente einfügen bei Index 1
my_list[1:1] = [ -1, -2]
print(my_list) #-> [7, -1, -2, 23, 42, 128]
  • my_list[0] = 7: Ein einzelnes Element ersetzt man, indem man es mit dem Index auswählt und dann einen neuen Wert zuweist.
  • my_list.append(128): An das Ende der Liste kann man mit .append(WERR) einen neuen Wert anfügen. Die Schreibweise mit dem Punkt . ist neu und vielleicht etwas verwirrend. Sie bedeutet, dass man "auf der Liste eine Methode aufruft". Die Details werden später bei den Klassen noch etwas genauer erläutert, hier reicht es erst einmal die Syntax zu akzeptieren, wie sie ist.
  • my_list[1:1] = [ -1, -2]: Man kann auch mehrere Elemente in der Liste einfügen/ersetzen. Hierzu gibt man in den eckigen Klammern durch Doppelpunkt (:) getrennt das erste und letzte zu ersetzende Element an, wobei die zweite Zahl exklusive ist. Hier im Beispiel wird mit [1:1] kein Element ersetzt, sondern die Elemente werden vor dem Element mit dem Index 1 eingefügt. Will man das Element am Index 1 ersetzen, muss man [1:2] schreiben.

Man kann auch mehrere Elemente auf einmal ersetzen:

# Element am Index 1 ersetzen
my_list = [0, 23, 42]
my_list[1:2] = [ -1, -2]
print(my_list) #-> [0, -1, -2, 42]

# Elemente am Index 1 und 2 ersetzen
my_list = [0, 23, 42]
my_list[1:3] = [ -1, -2]
print(my_list) #-> [0, -1, -2]

Wenn man in der Zuweisung eine Variable verwendet, dann wird in die Liste übernommen

  • bei einfachen Datentypen der Wert der Variablen
  • bei Referenzvariablen die Referenz
x = -2
my_list = [0, 23, 42]
my_list[1:2] = [x, -3]
print(my_list) #-> [0, -2, -3, 42]

# Variable x wird verändert, wirkt sich aber nicht auf die Liste aus
x = 4
print(my_list) #-> [0, -2, -3, 42]

Das Beispiel zeigt, dass man die Variable x nach dem Eintragen in die Liste ändern kann, ohne dass sich dies auf die Liste auswirkt.

Dies gilt aber nicht bei Referenzvariablen, da bei diesen kein Wert, sondern eine Referenz auf die Daten vorliegt. Eine Liste ist z. B. etwas, das über eine Referenzvariable verwaltet wird, wie das folgende Beispiel zeigt:

Referenztyp in Liste
x = [ -1, -2, -3 ]
my_list = [0, 23, 42]
my_list[1:2] = [x, -3]
print(my_list) #-> [0, [-1, -2, -3], -3, 42]

x.append("Ooops")
print(my_list) #-> 0, [-1, -2, -3, 'Ooops'], -3, 42]

Slicing und Verketten

Manchmal möchte man von einer Liste einen Ausschnitt erhalten, eine Liste abschneiden oder zwei Listen miteinander verketten. Hierzu bietet Python das Slicing und den +-Operator an.

  • Aus Listen können Sublisten erstellt werden (Slicing): [von:bis] (exklusive bis)
  • Listen können mit + verkettet werden
my_list = [ 1, 2, 3, 4, 5 ]
my_list[0:2] # -> [1, 2]
my_list[2:3] # -> [3]
my_list[2:4] # -> [3, 4]
my_list[1:] # -> [2, 3, 4, 5]
my_list[:3] # -> [ 1, 2, 3]

new_list = [ 'a', 'b', 'c' ]

verkettet = my_list + new_list
# [ 1, 2, 3, 4, 5, 'a', 'b', 'c' ]

Das Beispiel zeigt, wie durch Slicing aus der Liste my_list neue Listen (Slices) erstellt werden. Es handelt sich hierbei um echte Kopien der Liste, d. h. ein Slice ist nicht nur eine Sicht auf die vorhandene Liste, sondern eine neue Liste. Dies sieht man an folgendem Beispiel:

Slices sind Kopien
my_list = [ 1, 2, 3, 4, 5 ]
slice = my_list[0:2] # -> [1, 2]

my_list[0] = 99
print(my_list) # -> [ 99, 2, 3, 4, 5 ]
print(slice) # -> [1, 2]

Dasselbe gilt auch für die Verkettung von Listen mit +:

Verkettungen sind Kopien
a = [ 1, 2, 3 ]
b = [ 4, 5, 6 ]
new_list = a + b # -> [ 1, 2, 3, 4, 5, 6 ]

a[0] = 99
print(a) # -> [ 99, 2, 3 ]
print(new_list) # -> [ 1, 2, 3, 4, 5, 6 ]

Man kann bei der Angabe des Slices noch eine Schrittweite angeben, sodass die vollständige Syntax zur Erzeugung eines Slices [von:bis:schrittweite] ist.

Slice mit Schrittweite
my_list = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
slice = my_list[0:8:3] # -> [1, 2]
print(slice) # -> [1, 4, 7]

Hier werden die Elemente vom Index 0 bis zum Index 7 (die 8 ist exklusive) adressiert, von diesen Elementen aber nur jeder dritte Index, also 0, 3, 6 und damit die Elemente [1, 4, 7]. Man kann sich die Funktionsweise des durch folgende Funktion verdeutlichen.

Slice als Funktion
def slice(list, start, end, step = 1):
    i = start
    result = []
    while i < end:
        result.append(list[i])
        i = i + step
    return result

my_list = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
s = slice(my_list, 0, 8, 3)
print(s)

Im Vergleich zu diesem Beispiel ist die eingebaute Syntax von Python schon deutlich kompakter.

Multiplikation

Nicht nur der +-Operator ist für Listen erlaubt, sondern auch der *-Operator. Man kann Listen also multiplizieren.

Möglich ist nur eine Multiplikation einer Liste mit einer Ganzzahl n. Die Liste wird dann n-Mal mit sich selbst verkettet.

  • Listen können multipliziert werden
Beispiel: Listen multiplizieren
my_list = [ 'a', 'b' ]

my_list * 2
# [ 'a', 'b', 'a', 'b' ]

2 * my_list
# [ 'a', 'b', 'a', 'b' ]

Kopieren einer Liste

Listen sind Datentypen, die über Referenzvariablen verarbeitet werden. Das bedeutet, dass man eine Liste durch die Zuweisung an eine andere Variable nicht kopiert, sondern nur die Referenz auf die Liste.

Kopie der Referenz auf die Liste
a = [ 1, 2, 3 ]
b = a

a[0] = -3
print(a) # -> [ -3, 2, 3 ]
print(b) # -> [ -3, 2, 3 ]

Es gibt in diesem Beispiel nur eine Liste mit den Elementen [ 1, 2, 3 ]. Die Zuweisung b = a kopiert nicht die Liste mit ihrem Inhalt, nur die Referenz wird kopiert. Beide Variablen (a und b) zeigen auf dasselbe Listen-Objekt. Eine Änderung, die ich über die Referenz a an der Liste vornehme, ist damit auch über die Variable b sichtbar.

Will ich eine "echte" Kopie der Liste, d. h. eine Kopie nicht nur der Referenz, sondern auch der Elemente, kann ich den Slice-Operator dafür verwenden. Da Slices immer Kopien der Listen sind, führt ein Slice [0:länge] zu einer vollständigen Kopie der Liste. Jedes Mal vorher die Länge bestimmen zu müssen ist aber recht unhandlich, sodass mit [:] eine verkürzte Form zur Verfügung steht, die alle Elemente kopiert.

Kopie der Liste
a = [ 1, 2, 3 ]
b = a[:] # oder b = list(a)

a[0] = -3
print(a) # -> [ -3, 2, 3 ]
print(b) # -> [ 1, 2, 3 ]

In diesem Beispiel wird die Liste kopiert, sodass a und b auf zwei unterschiedliche Listen-Objekte verweisen. Eine Änderung über a betrifft nur dessen Kopie der Liste, b bleibt davon unbeeindruckt.

Packing und Unpacking

Im Kapitel zu den Funktionen haben wir bereits gesehen, dass Funktionen über den Umweg der Liste mehrere Werte auf einmal zurückgeben können. Hierbei handelt es sich um einen ganz allgemeinen Mechanismus, den man als packing und unpacking bezeichnet.

Beim unpacking weist man eine Liste mehreren Variablen zu.

  • unpacking: Listen werden automatisch entpackt, wenn auf der linken Seite der Zuweisung mehrere Variablen stehen
  • Die Anzahl der Variablen muss mit den Listenelementen übereinstimmen
Unpacking einer Liste
my_list = [ 1, 2, 3, 4 ]
a, b, c, d = my_list # a=1, b=2, c=3, d=4

x, y, z = my_list
# ValueError: too many values to unpack (expected 3)

a, b, c, d, e = my_list # a=1, b=2, c=3, d=4
# ValueError: not enough values to unpack (expected 5, got 4)

Gegensatz zum unpacking werden beim packing beliebig viele Variablen zu einem Tuple umgewandelt, wenn links von einer Zuweisung mehr als eine Variable steht.

Tuple wurden an dieser Stelle noch nicht erläutert und kommen später in der Vorlesung vor; man kann sie sich aber einfach als Listen vorstellen, die nicht verändert werden können.

  • packing: Variablen werden zu einem Tuple (siehe unten) gepackt, wenn sie auf der rechten Seite der Zuweisung stehen
Packing von Variablen zu einem Tuple
my_tuple = a, b, c, d
# (1, 2, 3, 4)

Nicht immer will man, dass die Variablen als Tuple verpackt werden, sondern hätte lieber eine Liste. In diesem Fall muss man die Variablen in eckige Klammern setzen. Es handelt sich hierbei nicht mehr um ein echtes packen der Variablen, da wir einfach eine Liste mit ihnen als Elementen erzeugen aber vom Ergebnis her gibt es keinen Unterschied.

Variablen zu einer Liste packen
new_list = [ a, b, c, d ]
# [1, 2, 3, 4]

Funktionen für Listen

Es gibt in Python eine Reihe von Funktionen, mit denen man Listen ver- und bearbeiten kann. Weiter oben wurde bereits die append-Methode eingeführt, es gibt aber noch weitere Funktionen.

Einige Funktionen bekommen die Liste als Argument (z. B. len), andere werden auf der Liste aufgerufen (z. B. append). Wenn eine Funktion auf einem Objekt aufgerufen werden kann, dann sprechen wir von einer Methode. Somit sind append, count, insert etc. Methoden der Liste. Bei Methoden steht vor dem Punkt die Variable, die auf das Objekt verweist, auf dem die Methode aufgerufen werden soll und rechts vom Punkt der Name der Methode. Man kann Methoden mental auf Funktionen abbilden, indem man ganz allgemein o.methode(parameter) durch methode(o, parameter) ersetzt.

Python geht mit der Mischung aus Funktionen und Methoden einen sehr eigenwilligen Weg, dem andere Programmiersprachen nicht folgen. Hier ist entweder alles über Funktionen abgebildet (C) oder alles über Methoden (Ruby, Java). Es gibt auch keinen tieferen Grund für diese Entscheidung, außer dass der Erfinder der Sprache es so eleganter fand. Wir müssen also einfach damit leben.

  • len(xs): Länge der Liste
  • xs.append(x): x an xs anhängen
  • xs.count(x): Anzahl der x in xs zählen
  • xs.insert(i, x): x an der Stelle i in xs einfügen
  • xs.sort(): xs sortieren
  • xs.remove(x): x aus xs entfernen
  • xs.pop(): letztes Element on xs entfernen und zurückgeben
  • x in xs: testen, ob xs ein x enthält
  • del list[i]: entfernt Element mit dem Index i aus list
my_list = [ 5, 4, 3, 2 ]

len(my_list) # -> 4

my_list.append(1) # -> [ 5, 4, 3, 2, 1 ]

my_list.count(3) # -> 1

my_list.insert(2, 3.5) # -> [ 5, 4, 3.5, 3, 2, 1 ]

my_list.sort() # -> [1, 2, 3, 3.5, 4, 5]

my_list.remove(3.5) # -> [1, 2, 3, 4, 5]
my_list.pop() # -> [1, 2, 3, 4]
del my_list[1] # -> [1, 3, 4]

4 in my_list # -> True

Über Listen iterieren

Im Kapitel zu den Kontrollstrukturen wurde bereits die for-Schleife vorgestellt. Sie dient in Python dazu, über die Elemente einer Liste zu laufen, was als iterieren bezeichnet wird.

  • Mit for kann man über die Elemente einer Liste laufen
filme = [ 'Pulp Fiction', 'Kill Bill', 'Reservoir Dogs' ]

for f in filme:
    print(f)
Ausgabe
Pulp Fiction
Kill Bill
Reservoir Dogs

Die for-Schleife liefert uns bei jedem Durchlauf das gerade aktuelle Element der Liste in der sogenannten Laufvariablen. Dies ist sehr komfortabel, weil wir uns nicht mit den Indices der Elemente herumschlagen müssen und auch die Frage, wann die Liste zu Ende ist kein Problem darstellt.

In manchen Fällen benötigt man aber neben den Elementen der Liste bei der Iteration auch deren Index. Hier kann man die enumerate-Funktion verwenden.

  • Mit enumerate kann man über Elemente und Index gleichzeitig iterieren
filme = [ 'Pulp Fiction', 'Kill Bill', 'Reservoir Dogs' ]

for index, f in enumerate(filme):
    print(index, f)
Ausgabe
0 Pulp Fiction
1 Kill Bill
2 Reservoir Dogs

Die enumerate-Funktion liefert ein Objekt zurück, das man in der for-Schleife anstelle der Liste verwenden kann. Bei jedem Schleifendurchlauf bekommt man dann ein Tuple, bestehend aus Index und Element, wie das folgende Beispiel zeigt:

filme = [ 'Pulp Fiction', 'Kill Bill', 'Reservoir Dogs' ]

for t in enumerate(filme):
    print(t)
Ausgabe
(0, 'Pulp Fiction')
(1, 'Kill Bill')
(2, 'Reservoir Dogs')

Sinnvollerweise packt man dieses Tuple aber direkt per unpacking wieder aus, sodass die for-Schleife zwei Variablen vor dem in hat: for index, f in enumerate(filme):

sum

Wenn eine Liste numerische Daten (Ganzzahlen oder Fließkommazahlen) enthält, kann man alle Elemente mit Hilfe der sum-Funktion aufaddieren lassen.

  • Die Funktion sum summiert alle Elemente einer Liste
l = [ 1, 2, 3, 4 ]
summe = sum(l) # -> 10

# Alternativ zu Fuß
summe = 0
for e in l:
    summe += e

Bei nicht-numerischen Daten bekommt man bei sum einen Fehler.

sum bei nicht-numerischen Daten
a = ["A", "B"]
s = sum(a)
# TypeError: unsupported operand type(s) for +: 'int' and 'str'

filter

Man kann eine Liste filtern, d. h. Elemente entfernen, indem man über die gesamte Liste läuft und nur die gewünschten Elemente in das Ergebnis übernimmt.

Filtern einer Liste
my_list = [ 1, 2, 3, 4, 5, 6, 7, 8 ]
gerade = []

for e in my_list:
    if e % 2 == 0:
        gerade.append(e)

print(gerade) # -> [2, 4, 6, 8 ]

Da es sich hierbei aber um einen sehr häufigen Vorgang handelt, hat Python eine Methode filter, die diese Aufgabe elegant übernimmt.

  • Mit der Funktion filter kann man die Elemente einer Liste filtern
  • Alle Elemente, für die die Lambda-Funktion True zurückgibt, werden übernommen
my_list = [ 1, 2, 3, 4, 5, 6, 7, 8 ]
gerade = list(filter(lambda e: e % 2 == 0, my_list))

print(gerade)
# -> [2, 4, 6, 8]

Entscheidend in dem Beispiel ist der Rückgabewert der Lambda-Funktion lambda e: e % 2 == 0: Gibt sie True zurück, weil der Wert ohne Rest durch zwei Teilbar, also gerade ist, wird das Element in die neue Liste übernommen. Andernfalls wird das Element verworfen.

map

  • Die Funktion map erlaubt es, die Elemente einer Liste zu bearbeiten
filme = [ 'Pulp Fiction', 'Kill Bill', 'Reservoir Dogs' ]
filme_gross = list(map(lambda f: f.upper(), filme))

print(filme_gross)
# -> ['PULP FICTION', 'KILL BILL', 'RESERVOIR DOGS']

In dem Beispiel taucht eine neue Methode auf: list. Sie nimmt ein Objekt, das iterierbar ist, d. h. in einer for-Schleife nach dem in verwendet werden kann, läuft über alle Elemente und gibt sie als Liste zurück. Beispiele für solche Objekte sind ein range-, map-, filter- oder enumerate-Objekt, die von den gleichnamigen Methoden erzeugt werden. Die Implementierung von list kann man sich also wie folgt vorstellen:

# Implementierung von list
def list(iterable):
    result = []
    for e in iterable:
        result.append(e)
    return result

Die Methode map ist ein mächtiges Werkzeug zur Bearbeitung von Daten in Python (und anderen Programmiersprachen).

map

  • erzeugt eine neue Liste von der Größe der ursprünglichen,
  • läuft über die Liste und wendet die übergebene Funktion auf das aktuelle Element an und
  • schreibt den Rückgabewert des Blockes an die korrespondierende Position der neuen die.

Nach Ablauf von map hat man eine neue Liste, bei der jedes Element der ursprünglichen entspricht allerdings nach Anwendung der Funktion.

Wollte man die map-Methode mit einer Schleife nachbauen, würde aus dem Beispiel

map
a = list(map(lambda x: x*x, [ 1, 2, 3, 4 ]))

folgender Python-Code entstehen:

map von Hand programmiert
f = lambda x: x*x
a = []
for x in [ 1, 2, 3, 4 ]:
    a.append(f(x))

Warum liefert map keine Liste, sondern ein spezielles Objekt, das man erst mit list wieder in eine Liste konvertieren muss? Der Grund liegt darin, dass man mehrere Operationen auf einer Liste mit map, sum etc. hintereinander schalten kann und es nicht effizient wäre, jedes Mal eine Liste als Zwischenwert zu erzeugen.

map und sum
l = [ 1, 2, 3, 4 ]
s = sum(map(lambda x: x*x, l))
print(s) # -> 30

In diesem Beispiel wird die Summe über die Quadrate der Elemente bestimmt, ohne extra eine Liste als Zwischenwert zu benötigen.

reduce

map verwendet man normalerweise zusammen mit einer anderen Funktion reduce, und kann so ein Verfahren namens Map/Reduce implementieren. Es ist ein mächtiges Verfahren, um große Datenmengen zu verarbeiten. Bekannt geworden ist es durch Google, das seinen Suchindex mithilfe von Map/Reduce bearbeitet, siehe Jeffrey Dean and Sanjay Ghemawat (2004). MapReduce: Simplified Data Processing on Large Clusters. OSDI'04: Sixth Symposium on Operating System Design and Implementation.

  • Als Gegenstück zu map reduziert reduce die Werte mehrerer Elemente auf ein Element
import functools as f
a = [ 1, 2, 3, 4 ]
r = f.reduce(lambda sum, x: sum + x, a)
print(r) # => 10

reduce reduziert alle Werte einer Liste auf einen einzigen Wert. (Dieser einzige Wert kann natürlich selbst auch wieder eine Liste sein, sodass man mit den Methoden sehr vielseitige Dinge tun kann).

reduce(lambda a, b: , list, startvalue) geht dabei wie folgt vor:

  1. a wird mit dem Wert s initialisiert
  2. Die Lambda-Funktion wird mit dem Wert a und dem aktuellen Element b aufgerufen
  3. Der Rückgabewert der Lambda-Funktion wird in a gespeichert
  4. Weiter bei 2. bis die Liste komplett durchlaufen wurde
  5. Liste Collection durchlaufen, gibt den letzten Rückgabwert der Lambda-Funktion zurück

Am Beispiel

import functools as f
a = [ 1, 2, 3, 4 ]
r = f.reduce(lambda sum, x: sum + x, a, 100)
print(r) # => 110

soll dies schrittweise aufgezeigt werden:

# sum x Lamdba-Rückgabe
1 100 1 101
2 101 2 103
3 103 3 106
4 106 4 110

Guido van Rossum mag persönlich weder map noch reduce und konnte sich insofern durchsetzen, als dass reduce in das Modul functools verbannt wurde.

List Comprehensions

Python hat ein außergewöhnliches Feature, das man aus keiner anderen Programmiersprache kennt: die List Comprehensions. Sie erlauben es, Liste durch Angabe einer erzeugenden Funktion mit Werten zu befüllen. Diese Funktion muss allerdings nicht als Funktion oder Lambda formuliert werden, sondern kann direkt in den eckigen Klammern bei der Listenerzeugung genutzt werden.

  • List Comprehensions sind ein originäres Python-Feature zum Erstellen von Listen
my_list = [ i**2 for i in range(5) ]
print(my_list) # -> [0, 1, 4, 9, 16]

ints = [1, 3, 10]
[i*2 for i in ints] # [2, 6, 20]

[[i, j] for i in ints for j in ints if i != j]
# [[1, 3], [1, 10], [3, 1], [3, 10], [10, 1], [10, 3]]

Im ersten Beispiel wird über den Bereich von 0–4 mit Hilfe der range-Funktion iteriert und die Liste wird aus den Quadraten dieser Werte erzeugt.

Das zweite Beispiel zeigt, dass für eine List Comprehension eine andere Liste als Ausgangspunkt dienen kann, hier die Liste ints.

Im dritten Beispiel wird eine mehrdimensionale Liste erzeugt, wobei zusätzlich zu den Iterationen noch eine Bedingung verwendet wird, die nur ungleiche Werte für i und j zulässt.

Tuples als unveränderliche Listen

Mit Tuples hat Python einen weiteren Datentyp zur Darstellung von Sammlungen von gleichartigen Daten. Von der Verwendung sind Tuple analog zu Listen, nur dass man sie nach dem Anlegen nicht mehr verändern kann.

Um Tuples und Listen unterscheiden zu können, definiert man Tuple mit runden Klammern (()) und Listen mit eckigen Klammern ([]).

  • Tuples sind ähnlich wie Listen aber unveränderlich, d. h. die Elemente können später nicht mehr geändert werden
my_tuple = (1, 2, 3, 4)
my_tuple[0] # -> 1
my_tuple[1] # -> 2

my_tuple[1:3] # -> (2, 3)
my_tuple[:3] # -> (1, 2, 3)
my_tuple[2:] # -> (3, 4)

my_tuple[0] = 7 # Fehler
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# TypeError: 'tuple' object does not support item assignment

Packing / Unpacking

  • Tuples erlauben es, Werte auf mehrere Variablen zu verteilen (unpacking) oder
  • Werte aus mehreren Variablen in einem Tuple zu sammeln (packing)
# Packing
t = 'A', 'B', 'C'
print(t) # -> ('A', 'B', 'C')

# Unpacking
a, b, c = t
print(a) # -> 'A'
print(b) # -> 'B'
print(c) # -> 'C'

Wenn eine Funktion in Python mehrere Rückgabewerte liefert, geschieht dies hinter den Kulissen über den Umweg von Tuplen (siehe oben).

  • Über Tuples können Funktionen mehr als einen Wert zurückgeben
def my_function():
    return 'A', 'B', 'C'

x = my_function()
print(x) # -> ('A', 'B', 'C')

a, b, c = my_function()
print(a) # -> 'A'
print(b) # -> 'B'
print(c) # -> 'C'

Copyright © 2022 Thomas Smits