5. Datenstrukturen

Dieses Kapitel beschreibt einige Dinge, die Sie bereits kennengelernt haben, detaillierter und fügt auch einige neue hinzu.

5.1. Mehr über Listen

Der Listendatentyp hat einige weitere Methoden. Hier sind alle Methoden von Listenobjekten

list.append(x)

Fügt ein Element am Ende der Liste hinzu. Ähnlich wie a[len(a):] = [x].

list.extend(iterable)

Erweitert die Liste, indem alle Elemente aus dem Iterable angehängt werden. Ähnlich wie a[len(a):] = iterable.

list.insert(i, x)

Fügt ein Element an einer bestimmten Position ein. Das erste Argument ist der Index des Elements, vor dem eingefügt werden soll, so dass a.insert(0, x) am Anfang der Liste einfügt und a.insert(len(a), x) äquivalent zu a.append(x) ist.

list.remove(x)

Entfernt das erste Vorkommen von x aus der Liste. Löst einen ValueError aus, wenn kein solches Element vorhanden ist.

list.pop([i])

Entfernt das Element an der angegebenen Position in der Liste und gibt es zurück. Wenn kein Index angegeben ist, entfernt a.pop() das letzte Element der Liste und gibt es zurück. Löst einen IndexError aus, wenn die Liste leer ist oder der Index außerhalb des Listenbereichs liegt.

list.clear()

Entfernt alle Elemente aus der Liste. Ähnlich wie del a[:].

list.index(x[, start[, end]])

Gibt den nullbasierten Index des ersten Vorkommens von x in der Liste zurück. Löst einen ValueError aus, wenn kein solches Element vorhanden ist.

Die optionalen Argumente start und end werden wie in der Slice-Notation interpretiert und dienen dazu, die Suche auf eine bestimmte Teilsequenz der Liste zu beschränken. Der zurückgegebene Index wird relativ zum Beginn der vollständigen Sequenz und nicht zum start-Argument berechnet.

list.count(x)

Gibt die Anzahl der Vorkommen von x in der Liste zurück.

list.sort(*, key=None, reverse=False)

Sortiert die Elemente der Liste an Ort und Stelle (die Argumente können zur Anpassung der Sortierung verwendet werden, siehe sorted() für deren Erklärung).

list.reverse()

Kehrt die Reihenfolge der Elemente der Liste an Ort und Stelle um.

list.copy()

Gibt eine flache Kopie der Liste zurück. Ähnlich wie a[:].

Ein Beispiel, das die meisten Listenmethoden verwendet

>>> fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
>>> fruits.count('apple')
2
>>> fruits.count('tangerine')
0
>>> fruits.index('banana')
3
>>> fruits.index('banana', 4)  # Find next banana starting at position 4
6
>>> fruits.reverse()
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']
>>> fruits.append('grape')
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']
>>> fruits.sort()
>>> fruits
['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']
>>> fruits.pop()
'pear'

Sie haben vielleicht bemerkt, dass Methoden wie insert, remove oder sort, die nur die Liste modifizieren, keinen Rückgabewert ausgeben – sie geben das Standard- None zurück. [1] Dies ist ein Designprinzip für alle veränderlichen Datenstrukturen in Python.

Etwas anderes, das Ihnen vielleicht auffällt, ist, dass nicht alle Daten sortiert oder verglichen werden können. Zum Beispiel sortiert sich [None, 'hello', 10] nicht, da Ganzzahlen nicht mit Zeichenketten verglichen werden können und None nicht mit anderen Typen verglichen werden kann. Außerdem gibt es einige Typen, für die keine definierte Ordnungsrelation besteht. Zum Beispiel ist 3+4j < 5+7j kein gültiger Vergleich.

5.1.1. Listen als Stacks verwenden

Die Listenmethoden machen es sehr einfach, eine Liste als Stack zu verwenden, bei dem das zuletzt hinzugefügte Element als erstes abgerufen wird („Last-In, First-Out“). Um ein Element auf den Stack zu legen, verwenden Sie append(). Um ein Element vom Stack zu holen, verwenden Sie pop() ohne expliziten Index. Zum Beispiel

>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]

5.1.2. Listen als Queues verwenden

Es ist auch möglich, eine Liste als Queue zu verwenden, bei der das zuerst hinzugefügte Element als erstes abgerufen wird („First-In, First-Out“); Listen sind jedoch nicht effizient für diesen Zweck. Während das Anhängen und Entfernen am Ende einer Liste schnell ist, ist das Einfügen oder Entfernen am Anfang einer Liste langsam (da alle anderen Elemente um eine Position verschoben werden müssen).

Zur Implementierung einer Queue verwenden Sie collections.deque, die entwickelt wurde, um schnelles Anhängen und Entfernen an beiden Enden zu ermöglichen. Zum Beispiel

>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry")           # Terry arrives
>>> queue.append("Graham")          # Graham arrives
>>> queue.popleft()                 # The first to arrive now leaves
'Eric'
>>> queue.popleft()                 # The second to arrive now leaves
'John'
>>> queue                           # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])

5.1.3. List Comprehensions

List Comprehensions bieten eine prägnante Möglichkeit, Listen zu erstellen. Häufige Anwendungen sind die Erstellung neuer Listen, bei denen jedes Element das Ergebnis einiger Operationen ist, die auf jedes Mitglied einer anderen Sequenz oder eines Iterables angewendet werden, oder die Erstellung einer Teilsequenz dieser Elemente, die eine bestimmte Bedingung erfüllen.

Angenommen, wir möchten eine Liste von Quadraten erstellen, wie zum Beispiel

>>> squares = []
>>> for x in range(10):
...     squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Beachten Sie, dass dies eine Variable namens x erstellt (oder überschreibt), die auch nach Abschluss der Schleife noch existiert. Wir können die Liste der Quadrate ohne Seiteneffekte berechnen, indem wir

squares = list(map(lambda x: x**2, range(10)))

oder äquivalent

squares = [x**2 for x in range(10)]

was prägnanter und lesbarer ist.

Eine List Comprehension besteht aus Klammern, die einen Ausdruck gefolgt von einer for-Klausel enthalten, dann null oder mehr for- oder if-Klauseln. Das Ergebnis ist eine neue Liste, die aus der Auswertung des Ausdrucks im Kontext der folgenden for- und if-Klauseln resultiert. Zum Beispiel kombiniert diese List Comprehension die Elemente zweier Listen, wenn sie nicht gleich sind.

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

und es ist äquivalent zu

>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Beachten Sie, wie die Reihenfolge der for- und if-Anweisungen in beiden Snippets gleich ist.

Wenn der Ausdruck ein Tupel ist (z. B. das (x, y) im vorherigen Beispiel), muss er in Klammern gesetzt werden.

>>> vec = [-4, -2, 0, 2, 4]
>>> # create a new list with the values doubled
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]
>>> # filter the list to exclude negative numbers
>>> [x for x in vec if x >= 0]
[0, 2, 4]
>>> # apply a function to all the elements
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
>>> # call a method on each element
>>> freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
>>> # create a list of 2-tuples like (number, square)
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> # the tuple must be parenthesized, otherwise an error is raised
>>> [x, x**2 for x in range(6)]
  File "<stdin>", line 1
    [x, x**2 for x in range(6)]
     ^^^^^^^
SyntaxError: did you forget parentheses around the comprehension target?
>>> # flatten a list using a listcomp with two 'for'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

List Comprehensions können komplexe Ausdrücke und verschachtelte Funktionen enthalten.

>>> from math import pi
>>> [str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']

5.1.4. Verschachtelte List Comprehensions

Der anfängliche Ausdruck in einer List Comprehension kann ein beliebiger Ausdruck sein, einschließlich einer weiteren List Comprehension.

Betrachten Sie das folgende Beispiel einer 3x4-Matrix, die als Liste von 3 Listen der Länge 4 implementiert ist.

>>> matrix = [
...     [1, 2, 3, 4],
...     [5, 6, 7, 8],
...     [9, 10, 11, 12],
... ]

Die folgende List Comprehension transponiert Zeilen und Spalten.

>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

Wie wir im vorherigen Abschnitt gesehen haben, wird die innere List Comprehension im Kontext der folgenden for ausgewertet, so dass dieses Beispiel äquivalent zu

>>> transposed = []
>>> for i in range(4):
...     transposed.append([row[i] for row in matrix])
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

ist, was wiederum dasselbe ist wie

>>> transposed = []
>>> for i in range(4):
...     # the following 3 lines implement the nested listcomp
...     transposed_row = []
...     for row in matrix:
...         transposed_row.append(row[i])
...     transposed.append(transposed_row)
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

In der realen Welt sollten Sie integrierten Funktionen gegenüber komplexen Flussanweisungen den Vorzug geben. Die Funktion zip() würde für diesen Anwendungsfall gute Dienste leisten.

>>> list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]

Siehe Entpacken von Argumentlisten für Details zum Sternchen in dieser Zeile.

5.2. Die del-Anweisung

Es gibt eine Möglichkeit, ein Element aus einer Liste anhand seines Index anstatt seines Wertes zu entfernen: die del-Anweisung. Dies unterscheidet sich von der Methode pop(), die einen Wert zurückgibt. Die del-Anweisung kann auch verwendet werden, um Slices aus einer Liste zu entfernen oder die gesamte Liste zu leeren (was wir zuvor durch Zuweisung einer leeren Liste an den Slice getan haben). Zum Beispiel

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:]
>>> a
[]

del kann auch verwendet werden, um ganze Variablen zu löschen.

>>> del a

Wenn Sie danach auf den Namen a verweisen, ist dies ein Fehler (zumindest bis ihm ein anderer Wert zugewiesen wird). Wir werden später weitere Verwendungszwecke für del finden.

5.3. Tupel und Sequenzen

Wir haben gesehen, dass Listen und Zeichenketten viele gemeinsame Eigenschaften haben, wie z. B. Indexierungs- und Slice-Operationen. Sie sind zwei Beispiele für Sequenz-Datentypen (siehe Sequenztypen — list, tuple, range). Da Python eine sich entwickelnde Sprache ist, können weitere Sequenzdatentypen hinzugefügt werden. Es gibt auch einen weiteren standardmäßigen Sequenzdatentyp: das Tupel.

Ein Tupel besteht aus einer Reihe von durch Kommas getrennten Werten, zum Beispiel

>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
>>> u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # Tuples are immutable:
>>> t[0] = 88888
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # but they can contain mutable objects:
>>> v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])

Wie Sie sehen, werden Tupel bei der Ausgabe immer in Klammern eingeschlossen, damit verschachtelte Tupel korrekt interpretiert werden; sie können mit oder ohne umgebende Klammern eingegeben werden, obwohl oft sowieso Klammern notwendig sind (wenn das Tupel Teil eines größeren Ausdrucks ist). Es ist nicht möglich, einzelnen Elementen eines Tupels Werte zuzuweisen, jedoch ist es möglich, Tupel zu erstellen, die veränderliche Objekte wie Listen enthalten.

Obwohl Tupel ähnlich wie Listen erscheinen mögen, werden sie oft in verschiedenen Situationen und für unterschiedliche Zwecke verwendet. Tupel sind unveränderlich und enthalten normalerweise eine heterogene Sequenz von Elementen, auf die über Entpacken (siehe später in diesem Abschnitt) oder Indexierung (oder sogar über Attribute im Falle von namedtuples) zugegriffen wird. Listen sind veränderlich, und ihre Elemente sind normalerweise homogen und werden durch Iteration über die Liste abgerufen.

Ein spezielles Problem ist die Konstruktion von Tupeln mit 0 oder 1 Element: die Syntax hat einige zusätzliche Besonderheiten, um diese zu berücksichtigen. Leere Tupel werden durch ein leeres Klammerpaar konstruiert; ein Tupel mit einem Element wird konstruiert, indem ein Wert mit einem Komma folgt (es reicht nicht aus, einen einzelnen Wert in Klammern einzuschließen). Hässlich, aber effektiv. Zum Beispiel

>>> empty = ()
>>> singleton = 'hello',    # <-- note trailing comma
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)

Die Anweisung t = 12345, 54321, 'hello!' ist ein Beispiel für Tupel-Packing: die Werte 12345, 54321 und 'hello!' werden zu einem Tupel zusammengepackt. Die Umkehrung ist ebenfalls möglich.

>>> x, y, z = t

Dies wird passenderweise als Sequenz-Entpacken bezeichnet und funktioniert für jede Sequenz auf der rechten Seite. Sequenz-Entpacken erfordert, dass auf der linken Seite des Gleichheitszeichens genauso viele Variablen stehen wie Elemente in der Sequenz. Beachten Sie, dass Mehrfachzuweisung eigentlich nur eine Kombination aus Tupel-Packing und Sequenz-Entpacken ist.

5.4. Mengen

Python enthält auch einen Datentyp für Mengen. Eine Menge ist eine ungeordnete Sammlung ohne doppelte Elemente. Grundlegende Verwendungen sind Mitgliedschaftstests und das Eliminieren doppelter Einträge. Mengenobjekte unterstützen auch mathematische Operationen wie Vereinigung, Schnittmenge, Differenz und symmetrische Differenz.

Geschweifte Klammern oder die Funktion set() können zur Erstellung von Mengen verwendet werden. Hinweis: Um eine leere Menge zu erstellen, müssen Sie set() verwenden, nicht {}; letzteres erstellt ein leeres Dictionary, eine Datenstruktur, die wir im nächsten Abschnitt besprechen.

Hier ist eine kurze Demonstration.

>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> print(basket)                      # show that duplicates have been removed
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket                 # fast membership testing
True
>>> 'crabgrass' in basket
False

>>> # Demonstrate set operations on unique letters from two words
>>>
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a                                  # unique letters in a
{'a', 'r', 'b', 'c', 'd'}
>>> a - b                              # letters in a but not in b
{'r', 'd', 'b'}
>>> a | b                              # letters in a or b or both
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b                              # letters in both a and b
{'a', 'c'}
>>> a ^ b                              # letters in a or b but not both
{'r', 'd', 'b', 'm', 'z', 'l'}

Ähnlich wie bei List Comprehensions werden auch Mengen-Comprehensions unterstützt.

>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}

5.5. Dictionaries

Ein weiterer nützlicher Datentyp, der in Python integriert ist, ist das Dictionary (siehe Mapping-Typen — dict). Dictionaries werden manchmal in anderen Sprachen als „assoziative Speicher“ oder „assoziative Arrays“ gefunden. Im Gegensatz zu Sequenzen, die durch einen Bereich von Zahlen indiziert werden, werden Dictionaries durch Schlüssel indiziert, die jeder unveränderliche Typ sein kann; Zeichenketten und Zahlen können immer Schlüssel sein. Tupel können als Schlüssel verwendet werden, wenn sie nur Zeichenketten, Zahlen oder Tupel enthalten; wenn ein Tupel ein veränderliches Objekt direkt oder indirekt enthält, kann es nicht als Schlüssel verwendet werden. Listen können nicht als Schlüssel verwendet werden, da Listen durch Indexzuweisungen, Slice-Zuweisungen oder Methoden wie append() und extend() modifiziert werden können.

Am besten denkt man an ein Dictionary als eine Menge von Schlüssel: Wert-Paaren, mit der Anforderung, dass die Schlüssel eindeutig sind (innerhalb eines Dictionaries). Ein Klammerpaar erstellt ein leeres Dictionary: {}. Das Platzieren einer durch Kommas getrennten Liste von Schlüssel:Wert-Paaren innerhalb der Klammern fügt anfängliche Schlüssel:Wert-Paare zum Dictionary hinzu; dies ist auch die Art und Weise, wie Dictionaries ausgegeben werden.

Die Hauptoperationen auf einem Dictionary sind das Speichern eines Wertes mit einem bestimmten Schlüssel und das Extrahieren des Wertes anhand des Schlüssels. Es ist auch möglich, ein Schlüssel:Wert-Paar mit del zu löschen. Wenn Sie mit einem bereits vorhandenen Schlüssel speichern, wird der alte zugeordnete Wert vergessen.

Das Extrahieren eines Wertes für einen nicht vorhandenen Schlüssel durch Subskription (d[key]) löst einen KeyError aus. Um diesen Fehler beim Versuch, einen möglicherweise nicht vorhandenen Schlüssel abzurufen, zu vermeiden, verwenden Sie stattdessen die Methode get(), die None (oder einen angegebenen Standardwert) zurückgibt, wenn der Schlüssel nicht im Dictionary vorhanden ist.

Das Ausführen von list(d) für ein Dictionary gibt eine Liste aller im Dictionary verwendeten Schlüssel in Einfügungsreihenfolge zurück (wenn Sie es sortiert haben möchten, verwenden Sie stattdessen einfach sorted(d)). Um zu prüfen, ob ein einzelner Schlüssel im Dictionary vorhanden ist, verwenden Sie den in-Operator.

Hier ist ein kleines Beispiel mit einem Dictionary.

>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'jack': 4098, 'sape': 4139, 'guido': 4127}
>>> tel['jack']
4098
>>> tel['irv']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'irv'
>>> print(tel.get('irv'))
None
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'jack': 4098, 'guido': 4127, 'irv': 4127}
>>> list(tel)
['jack', 'guido', 'irv']
>>> sorted(tel)
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
>>> 'jack' not in tel
False

Der Konstruktor dict() erstellt Dictionaries direkt aus Sequenzen von Schlüssel-Wert-Paaren.

>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'guido': 4127, 'jack': 4098}

Zusätzlich können Dictionary-Comprehensions verwendet werden, um Dictionaries aus beliebigen Schlüssel- und Wertausdrücken zu erstellen.

>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}

Wenn die Schlüssel einfache Zeichenketten sind, ist es manchmal einfacher, Paare mithilfe von Schlüsselwortargumenten anzugeben.

>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'guido': 4127, 'jack': 4098}

5.6. Schleifentechniken

Beim Durchlaufen von Dictionaries können der Schlüssel und der entsprechende Wert gleichzeitig mit der Methode items() abgerufen werden.

>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
...     print(k, v)
...
gallahad the pure
robin the brave

Beim Durchlaufen einer Sequenz können der Index und der entsprechende Wert gleichzeitig mit der Funktion enumerate() abgerufen werden.

>>> for i, v in enumerate(['tic', 'tac', 'toe']):
...     print(i, v)
...
0 tic
1 tac
2 toe

Um über zwei oder mehr Sequenzen gleichzeitig zu iterieren, können die Einträge mit der Funktion zip() gepaart werden.

>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
...     print('What is your {0}?  It is {1}.'.format(q, a))
...
What is your name?  It is lancelot.
What is your quest?  It is the holy grail.
What is your favorite color?  It is blue.

Um über eine Sequenz in umgekehrter Reihenfolge zu iterieren, geben Sie zuerst die Sequenz in Vorwärtsrichtung an und rufen Sie dann die Funktion reversed() auf.

>>> for i in reversed(range(1, 10, 2)):
...     print(i)
...
9
7
5
3
1

Um über eine Sequenz in sortierter Reihenfolge zu iterieren, verwenden Sie die Funktion sorted(), die eine neue sortierte Liste zurückgibt, während die Quelle unverändert bleibt.

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for i in sorted(basket):
...     print(i)
...
apple
apple
banana
orange
orange
pear

Die Verwendung von set() auf einer Sequenz eliminiert Duplikate. Die Verwendung von sorted() in Kombination mit set() über eine Sequenz ist eine idiomatische Möglichkeit, über eindeutige Elemente der Sequenz in sortierter Reihenfolge zu iterieren.

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
...     print(f)
...
apple
banana
orange
pear

Es ist manchmal verlockend, eine Liste zu ändern, während Sie darüber iterieren; es ist jedoch oft einfacher und sicherer, stattdessen eine neue Liste zu erstellen.

>>> import math
>>> raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
>>> filtered_data = []
>>> for value in raw_data:
...     if not math.isnan(value):
...         filtered_data.append(value)
...
>>> filtered_data
[56.2, 51.7, 55.3, 52.5, 47.8]

5.7. Mehr über Bedingungen

Die Bedingungen, die in while- und if-Anweisungen verwendet werden, können beliebige Operatoren enthalten, nicht nur Vergleiche.

Die Vergleichsoperatoren in und not in sind Mitgliedschaftstests, die bestimmen, ob ein Wert in (oder nicht in) einem Container enthalten ist. Die Operatoren is und is not vergleichen, ob zwei Objekte wirklich dasselbe Objekt sind. Alle Vergleichsoperatoren haben die gleiche Priorität, die niedriger ist als die aller numerischen Operatoren.

Vergleiche können verkettet werden. Zum Beispiel testet a < b == c, ob a kleiner als b ist und obendrein b gleich c ist.

Vergleiche können mit den booleschen Operatoren and und or kombiniert werden, und das Ergebnis eines Vergleichs (oder eines anderen booleschen Ausdrucks) kann mit not negiert werden. Diese haben niedrigere Prioritäten als Vergleichsoperatoren; zwischen ihnen hat not die höchste Priorität und or die niedrigste, so dass A and not B or C äquivalent zu (A and (not B)) or C ist. Wie immer können Klammern verwendet werden, um die gewünschte Zusammensetzung auszudrücken.

Die booleschen Operatoren and und or sind sogenannte Short-Circuit-Operatoren: ihre Argumente werden von links nach rechts ausgewertet, und die Auswertung stoppt, sobald das Ergebnis feststeht. Wenn zum Beispiel A und C wahr sind, aber B falsch ist, wertet A and B and C den Ausdruck C nicht aus. Wenn der Rückgabewert eines Short-Circuit-Operators als allgemeiner Wert und nicht als boolescher Wert verwendet wird, ist es das zuletzt ausgewertete Argument.

Es ist möglich, das Ergebnis eines Vergleichs oder eines anderen booleschen Ausdrucks einer Variablen zuzuweisen. Zum Beispiel,

>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
>>> non_null = string1 or string2 or string3
>>> non_null
'Trondheim'

Beachten Sie, dass in Python, im Gegensatz zu C, die Zuweisung innerhalb von Ausdrücken explizit mit dem Walrus-Operator := erfolgen muss. Dies vermeidet eine häufige Klasse von Problemen, die in C-Programmen auftreten: die Eingabe von = in einem Ausdruck, wenn == beabsichtigt war.

5.8. Vergleich von Sequenzen und anderen Typen

Sequenzobjekte können typischerweise mit anderen Objekten desselben Sequenztyps verglichen werden. Der Vergleich verwendet eine lexikografische Ordnung: zuerst werden die ersten beiden Elemente verglichen, und wenn sie sich unterscheiden, bestimmt dies das Ergebnis des Vergleichs; wenn sie gleich sind, werden die nächsten beiden Elemente verglichen und so weiter, bis eine Sequenz erschöpft ist. Wenn zwei zu vergleichende Elemente selbst Sequenzen desselben Typs sind, wird der lexikografische Vergleich rekursiv durchgeführt. Wenn alle Elemente zweier Sequenzen gleich verglichen werden, gelten die Sequenzen als gleich. Wenn eine Sequenz eine anfängliche Untersequenz der anderen ist, ist die kürzere Sequenz die kleinere (geringere). Die lexikografische Ordnung für Zeichenketten verwendet die Unicode-Codepunktnummer zur Sortierung einzelner Zeichen. Einige Beispiele für Vergleiche zwischen Sequenzen desselben Typs.

(1, 2, 3)              < (1, 2, 4)
[1, 2, 3]              < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4)           < (1, 2, 4)
(1, 2)                 < (1, 2, -1)
(1, 2, 3)             == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab'))   < (1, 2, ('abc', 'a'), 4)

Beachten Sie, dass der Vergleich von Objekten verschiedener Typen mit < oder > legal ist, vorausgesetzt, die Objekte haben entsprechende Vergleichsmethoden. Zum Beispiel werden gemischte numerische Typen nach ihrem numerischen Wert verglichen, sodass 0 gleich 0.0 ist, usw. Andernfalls wird der Interpreter anstatt einer willkürlichen Ordnung eine TypeError-Ausnahme auslösen.

Fußnoten