Python Sequenzen (C) 2019-2025 T.Birnthaler OSTC GmbH ================ Doku --> docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range --> docs.python.org/3/library/array.html SEQUENZEN sind eine "GEORDNETE" Folge (Reihe) von ELEMENTEN, d.h. die Elemente haben eine REIHENFOLGE (erstes, zweites, ..., letztes). Jedem Element wird ein INDEX zugeordnet (Ganzzahl beginnend mit 0), über den es angesprochen wird. Der Index läuft AUFSTEIGEND von 0 bis Sequenz-Länge-1 bzw. ABSTEIGEND von -1 bis -Sequenz-Länge: s1 = "Hallo Welt" s2 = "" # String + leerer String t1 = ( True, 99, "hallo", 3.14 ) t2 = () # Tupel + leerer Tupel l1 = [ 123, 456, 789 ] l2 = [] # Liste + leere Liste 01234 # <-- POSITIVER Index (0 ... Länge-1) "hallo" # Sequenz (str) -1 # <-- NEGATIVER Index (-1 ... -Länge) = ABKÜRZUNG für len(S) - 1 -2 # len(S) - 2 -3 # len(S) - 3 -4 # len(S) - 4 -5 # len(S) - 5 * Die Zugriffsgeschwindigkeit auf ein ELEMENT über seinen INDEX ist UN-ABHÄNGIG von der Sequenz-LÄNGE und vom INDEX immer gleich schnell (RANDOM ACCESS). * Die Zugriffsgeschwindigkeit auf ein bestimmtes ELEMENT über seinen WERT (z.B. welchen Index hat ein bestimmter Wert oder wie häufig kommt ein Wert in der Sequenz vor) ist ABHÄNGIG von der Sequenz-LÄNGE und relativ langsam (erfordert das Durchsuchen der gesamten Sequenz). * In vielen anderen Programmiersprachen wird statt SEQUENZ der Begriff ARRAY verwendet (den Python in seiner Dokumentation vermeidet). Python verwendet in der Dokumentation auch den Begriff ITEM statt ELEMENT. Wichtige in Python eingebaute Sequenz-Datentypen mit ihren Eigenschaften: +-----------+------------+-----------------------------------+----------+ | Datentyp | Änderbar | Elemente | Elem.anz | +-----------+------------+-----------------------------------+----------+ | str | im-mutable | UTF-8 codierte Zeichen (1-4 Byte) | fix | | tuple | im-mutable | ALLE Python-Objekte | fix | | list | mutable | ALLE Python-Objekte | variabel | +-----------+------------+-----------------------------------+----------+ | bytes | im-mutable | Bytes mit Wert 0-255 bzw. 00-FF | fix | | bytearray | mutable | Bytes mit Wert 0-255 bzw. 00-FF | variabel | | array | mutable | Zahlen/Zeichen mit fester Größe | variabel | +-----------+------------+-----------------------------------+----------+ HINWEIS: "array" ist ein Modul aus der Standard-Bibliothek, das EIN-dimensionale Arrays von Ganzzahlen (signed/unsigned char/short/int/long/long long), Fließkommazahlen (float/double) und Unicode Zeichen (wchar_t) erlaubt. Einsatzzweck von "array": Erlaubt nur Elemente gleichen Typs und arbeitet speichersparend + effizient. --> Besser gleich die Bibliothek "NumPy" verwenden (diese unterstützt auch MEHR-dimensionale Arrays = Matrizen)! Folgende LESENDEN Operationen werden von (fast) ALLEN Sequenz-Datentypen (str, tuple, list, bytes, bytearray, array, ...) unterstützt (sowohl mutable als auch im-mutable). S und T sind Sequenzen des gleichen Datentyps, I, J, K, N sind Ganzzahlen und E ist ein Element, das die Einschränkung für die Elemente der Sequenz S erfüllt (meist ein beliebiges Objekt). ACHTUNG: Die Sequenz S bleibt UNVERÄNDERT! +--------------------+----------------------------------------------------+ | Operation | Bedeutung | +--------------------+----------------------------------------------------+ | for E in S: ... | ALLE Elem. E von S nach Index geordnet durchlaufen | +--------------------+----------------------------------------------------+ | E in S | Element E in S enthalten? | | E not in S | Element E in S nicht enthalten? | +--------------------+----------------------------------------------------+ | S + T | Verkettung von S und T | | S * N N * S | Sequenz S N-mal vervielfachen (N-mal verketten) | +--------------------+----------------------------------------------------+ | S == T | Sequenzen gleich (ALLE Elemente + Reihenfolge)? | Typ muss gleich sein! | S != T | Sequenzen ungleich (EIN Element oder Reihenfolge)? | Typ muss gleich sein! +--------------------+----------------------------------------------------+ | S < T | Sequenz S kleiner T? (hierarchisch!) | Typ muss gleich sein! | S <= T | Sequenz S kleiner gleich T? (hierarchisch!) | Typ muss gleich sein! | S > T | Sequenz S größer T? (hierarchisch!) | Typ muss gleich sein! | S >= T | Sequenz S größer gleich T? (hierarchisch!) | Typ muss gleich sein! +--------------------+----------------------------------------------------+ | S[I] Index | Element mit Index I (0 bis Länge-1) | | S[I:J] Slice | Elemente von Index I bis J-1 (mit Schrittweite 1) | "Verkappte" for-Schleife | S[I:J:K] Slice | Elemente von Index I bis J-1 mit Schrittweite K | "Verkappte" for-Schleife +--------------------+----------------------------------------------------+ | len(S) | Länge von S (Anzahl Elemente) | +--------------------+----------------------------------------------------+ | min(S) | Kleinstes Element in S (gemäß Vergleich "<") | | max(S) | Größtes Element in S (gemäß Vergleich "<") | | sum(S) | Summe der Elemente in S (müssen Zahlen sein) | +--------------------+----------------------------------------------------+ | all(S) | False falls mind. 1 Element False, sonst/leer True | Seltsam --> wieder vergessen! | any(S) | True falls mind. 1 Element True, sonst/leer False | Seltsam --> wieder vergessen! +--------------------+----------------------------------------------------+ | S.index(E[,I[,J]]) | Index des 1. Elements E in S (oder "ValueError") | | | (von Index I bis J-1; Standard: 0 bis len(S)-1) | | S.count(E) | Anzahl Vorkommen von Element E in S | +--------------------+----------------------------------------------------+ | reversed(S) | Elemente in umgekehrter Reihenfolge (Iterator) | | sorted(S,key, | Sortierte Liste der Elemente (gemäß Vergleich "<") | | reverse) | (key=MAPFUNC, reverse=True --> absteigend) | +--------------------+----------------------------------------------------+ HINWEIS: Index I, J sowie Schrittweite K dürfen NEGATIV sein (auch gemischt). HINWEIS: Indexzugriffe werden ÜBERWACHT, d.h. beim Zugriff über den Rand einer Sequenz hinaus erfolgt eine Exception "IndexError". HINWEIS: Die Formulierung "gemäß Vergleich <" heißt, dass ALLE Elemente per Operator "<" miteinander VERGLEICHBAR sind. D.h. entweder alle Elemente sind ZAHLEN (bool, int, float, complex, Decimal, Fraction) oder alle Elemente haben den GLEICHEN Datentyp. HINWEIS: INDEXZUGRIFFE S[I] und SLICING per S[I:J] und S[I:J:K] KOPIEREN ein Stück (Slice) der Sequenz S und dürfen aus einer beliebigen Kombination von positiven + negativen Indices bestehen. Slicing stellt letztlich eine SCHLEIFE dar. Startindex 0/-1, Endindex len(S)/-len(S)-1 und Schrittweite 1 dürfen weggelassen werden (bei sinnlosen Kombinationen entsteht eine LEERE Sequenz): S = "0123456789" # Sequenz (Element = positiver Index) -10987654321 # Negativer Index S[:] # --> '0123456789' = 1:1-Kopie (OK, pythonic) S[::] # --> '0123456789' = 1:1-Kopie (OK, un-pythonic) S[::1] # --> '0123456789' = 1:1-Kopie (OK, un-pythonic) S[0:] # --> '0123456789' = 1:1-Kopie (OK, un-pythonic) S[:len(S)] # --> '0123456789' = 1:1-Kopie (OK, un-pythonic) S[0:len(S)] # --> '0123456789' = 1:1-Kopie (OK, un-pythonic) S[0:len(S):1] # --> '0123456789' = 1:1-Kopie (OK, un-pythonic) Übliche (leicht verständliche) Slices: S[::2] # --> '02468' = Jedes 2. Element ab 1. Element S[1::2] # --> '13579' = Jedes 2. Element ab 2. Element S[5:] # --> '56789' = Ohne erste 5 Elemente S[:5] # --> '01234' = Erste 5 Elemente S[3:5] # --> '34' = 4. und 5. Element S[1:] # --> '123456789' = 1. Element weglassen S[:-1] # --> '012345678' = Letztes Element weglassen S[1:-1] # --> '12345678' = 1. + letztes Element weglassen S[::-1] # --> '9876543210' = Alle Elemente in umgek. Reihenfolge Bei NEGATIVER Index-Grenze ist die entsprechende positive Index-Grenze gemeint. Dies ist ungewöhnlich (und daher schwer verständlich). S[-5:] # --> '56789' = Letzte 5 Elemente S[:-5] # --> '01234' = Erste 5 Elemente S[-4:-5] # --> '' = Leer S[-5:-4] # --> '5' = Element mit Index 5 oder -5 S[-1:-10] # --> '' = Leer S[-10:-1] # --> '012345678' = Ohne letztes Element Bei NEGATIVER Schrittweite sind die Slice-Grenzen UMZUDREHEN (größere zuerst, dann kleinere. Dies ist ungewöhnlich (und daher schwer verständlich). S[::-1] # --> '9876543210' = Alle Elemente in umgek. Reihenfolge S[4::-1] # --> '43210' = Erste 5 Elemente in umgek. Reihenfolge S[:5:-1] # --> '9876' = Letzte 4 Elemente in umgek. Reihenfolge S[0:5:-1] # --> '' = Leer S[5:0:-1] # --> '54321' = Ohne erste 5 + letztes Element S[:0:-1] # --> '987654321' = Ohne 1. Element in umgek. Reihenfolge S[-1:0:-1] # --> '987654321' = Ohne 1. Element in umgek. Reihenfolge S[-1::-1] # --> '9876543210' = Alle Elemente in umgek. Reihenfolge S[-2::-1] # --> '876543210' = Ohne letztes Element in umgek. Reihenfolge S[-2:0:-1] # --> '87654321' = Ohne 1. + letztes Element in umgek. Reihenfolge S[:-6:-1] # --> '98765' = Letzte 5 Elemente in umgek. Reihenf. S[-1:-6:-1] # --> '98765' = Letzte 5 Elemente in umgek. Reihenf. HINWEIS: Slices berücksichtigen Index-Grenzen automatisch (kein "IndexError" möglich) und Slices mit LEEREM Index-Bereich liefern ein LEERES Ergebnis: S[100:100] # --> '' KEIN Element S[100:] # --> '' KEIN Element S[:100] # --> '0123456789' ALLE Elemente S[-100:-100] # --> '' KEIN Element S[-100:] # --> '0123456789' ALLE Elemente S[:-100] # --> '' KEIN Element S[100:-100] # --> '' KEIN Element S[-100:100] # --> '0123456789' ALLE Elemente HINWEIS: Funktion slice(STOP) bzw. slice(START, STOP [,STEP]) erzeugt ein SLICE-OBJEKT, das den entsprechenden Slice-Zugriff auf die Elemente einer Sequenz durchführt. Es gilt: S = "0123456789" # Sequenz (Element = positiver Index) I = 3; J = 7+1; K = 2 # START, STOP, STEP # S[slice(I, I+1)] # --> '3' = S[I] S[slice(I, J)] # --> '34567' = S[I:J] S[slice(I, J, None)] # --> '34567' = S[I:J:] S[slice(I, J, K)] # --> '357' = S[I:J:K] S[slice(I, None)] # --> '3456789' = S[I:] S[slice(I, None, None)] # --> '3456789' = S[I::] S[slice(I, None, K)] # --> '3579' = S[I::K] S[slice(J)] # --> '01234567' = S[:J] S[slice(None, J)] # --> '01234567' = S[:J] S[slice(None, J, None)] # --> '01234567' = S[:J:] S[slice(None, J, K)] # --> '0246' = S[:J:K] S[slice(None)] # --> '0123456789' = S[:] S[slice(None, None)] # --> '0123456789' = S[:] S[slice(None, None, None)] # --> '0123456789' = S[::] S[slice(None, None, K)] # --> '02468' = S[::K] Im-mutable Sequenzen -------------------- Folgende LESENDE Operation wird von im-mutable Sequenzen (str, tuple, bytes) ZUSÄTZLICH zu obigen unterstützt (S ist eine im-mutable Sequenz): ACHTUNG: Die Sequenz S bleibt UNVERÄNDERT! +--------------------+-------------------------------------------------------+ | Operation | Bedeutung | +--------------------+-------------------------------------------------------+ | hash(S) | Hashwert erstellen (eindeutig) | +--------------------+-------------------------------------------------------+ Mutable Sequenzen ----------------- Folgende SCHREIBENDEN Operationen werden von mutable Sequenzen (list, bytearray) ZUSÄTZLICH zu obigen Sequenz-Operationen unterstützt (S ist eine mutable Sequenz, T ist eine Sequenz oder ein Iterator des gleichen Datentyps, I, J, K, N sind Ganzzahlen und E ist ein Element, das die Einschränkung für die Elemente der Sequenz S erfüllt (meist ein beliebiges Objekt). ACHTUNG: Sequenz S wird VERÄNDERT (bleibt aber das gleiche Objekt)! ACHTUNG: Operationen += und *= sind auch auf String+Tupel anwendbar (im-mutable), erzeugen dabei aber "on-the-fly" einen NEUEN String / Tupel! +---------------------+--------------------------------------------------------+ | Operation | Bedeutung | +---------------------+--------------------------------------------------------+ | S[I] = E | Element mit Index I durch E ersetzen | | S[I:J] = T | Elemente mit Index I..J-1 durch Iterable T ersetzen | Slice | S[I:J:K] = T | Elemente mit Index I..J-1 in Schrittweite K ersetzen | Slice +---------------------+--------------------------------------------------------+ | del S[I] | Element mit Index I aus Liste entfernen | | del S[I:J] | Elemente mit Index I..J-1 aus Liste entfernen | Slice | del S[I:J:K] | Elemente mit Index I..J-1 in Schrittweite K entfernen | Slice +---------------------+--------------------------------------------------------+ | S.append(E) S += [E]| E am Sequenz-Ende anhängen S[len(S):len(S)] = [E] | | S.extend(T) S += T | Elemente von T anhängen S[len(S):len(S)] = T | | S.insert(I, E) | Element E bei Index I einfügen S[I:I+1] = [E] | +---------------------+--------------------------------------------------------+ | E = S.pop([I]) | Element bei Index I (STD: -1) entfernen und zurück | | S.remove(E) | Erstes Element mit Wert E entfernen (Suche!) | +---------------------+--------------------------------------------------------+ | S *= N | Sequenz S N-mal vervielfachen + verketten | | S.reverse() | Reihenfolge der Elemente umdrehen | | S.clear() | Sequenz S leeren (alle Elemente entfernen) del S[:] | | S2 = S.copy() | Shallow/Flache Kopie erzeugen S[:] | TODO +---------------------+--------------------------------------------------------+ HINWEIS: Index I, J sowie Schrittweite K dürfen NEGATIV sein (auch gemischt). list-Sequenz ------------ Folgende ändernde Operation wird von Listen zusätzlich zu den allgemeinen Sequenz-Operationen und den Operationen für mutable Sequenzen unterstützt: ACHTUNG: Die Liste L wird VERÄNDERT (bleibt aber das gleiche Objekt)! +--------------------+-------------------------------------------------------+ | Operation | Bedeutung | +--------------------+-------------------------------------------------------+ | L.sort(key,reverse)| Elemente aufsteigend sortieren (gemäß Vergleich "<") | | | (key=MAPFUNC, reverse=True --> absteigend) | +--------------------+-------------------------------------------------------+ HINWEIS: Die Formulierung "gemäß Vergleich <" bedingt, dass ALLE Elemente per Operator "<" miteinander VERGLEICHBAR sind. D.h. entweder alle Elemente sind ZAHLEN (bool, int, float, complex, Decimal, Fraction) oder alle Elemente haben den GLEICHEN Datentyp.