Level 05: Von Listen und Zeichenketten

Level 5: Von Listen und Zeichenketten #

Mit einem Index zugreifen #

Wenn Du Dir eine Zeichenkette (also z.B. so etwas wie 'Hallo') als eine Liste von Buchstaben oder Zeichen vorstellst, dann kommst Du wahrscheinlich recht schnell auf eine Gemeinsamkeit. Listen haben irgendwelche Elemente, und Zeichenketten ebenfalls. Beide lassen sich abzählen.

Diese Gemeinsamkeit kannst Du nutzen, wenn Du nicht alle Elemente einer Liste oder alle Buchstaben einer Zeichenkette bearbeiten möchtest, sondern nur ein bestimmtes. Probiere einmal folgendes in der REPL:

>>> z = 'Meine Zeichenkette'
>>> l = [1,2,3,4,5]
>>> z[6]
'Z'
>>> l[1]
2

z ist also eine Zeichenkette und l eine Liste. Durch die Angabe einer Zahl in eckigen Klammern lässt sich nun ein Element oder ein Zeichen an einer bestimmten Stelle ausgeben. (Die Zahl heißt übrigens Index.) In Python, wie in den meisten Programmiersprachen, fängt man bei der 0 zu zählen an. Daher gibt l[1] hier im Beispiel auch nicht 1 aus, sondern 2.

Von – bis #

Praktisch ist es oft auch, sich Teile von Zeichenketten oder Listen ausgeben zu lassen. Wenn Du Deine REPL noch offen hast, versuche einmal folgendes:

>>> z[0:5]
'Meine'

Diese Schreibweise gibt einen Bereich aus, und zwar vom ersten Index bis vor den nach dem : angegeben Index. (An Position 5 befindet sich im Beispiel das Leerzeichen.)
Für die Ausgabe vom Anfang an oder bis zum Ende gibt es eine beqeme Abkürzung:

>>> z[6:]
'Zeichenkette'
>>> l[:3]
[1, 2, 3]

Und auch für den Fall, dass Du Elemente von hinten abzählen möchtest, gibt es eine schnelle Möglichkeit:

>>> l[-2]
4
>>> l[-1]
5

Index out of range #

Der direkte Zugriff auf einzelne Elemente einer Liste oder Zeichenkette ist aber auch eine beliebte Fehlerquelle – dann nämlich, wenn Du auf eine Position zugreifen möchtest, die es in der Liste gar nicht gibt. Gerade, weil wir bei der 0 anfangen zu zählen, kann man sich da ganz prima vertun…

>>> l[5]
Traceback (most recent call last):
  File "<pyshell>", line 1, in <module>
IndexError: list index out of range

Hier (und auch sonst) ist es dann wirklich sinnvoll, wenn Du Dir die Fehlermeldung genau durchliest. »list index out of range« bedeutet ja nichts anderes als: »Der Index, den Du mir gegeben hast, ist gar nicht vorhanden.«

Off by one

Hinweis zur Einordnung

Während Python und vergleichbare Sprachen laufende Programme recht gnädig mit einer Fehlermeldung beenden, konnten solche off-by-one-Fehler in der Vergangenheit zu schwer zu entdeckenden Bugs oder ernsthaften Fehlern führen. In der Programmiersprache C wird der Speicher noch direkter vom Programm verwaltet, und Arrays (ähnlich den von uns verwendeten Listen) bieten Zugriff darauf über Indizes. Außerhalb des eigenen Bereichs liegen nun andere Daten im Speicher, und versehentlich auf solche zuzugreifen kann dann zu den beschriebenen Problemen führen.

Die Fehlerklasse ist so bekannt, dass sich sogar ein Podcast danach benannt hat.

Eingebaut: die Funktion len #

Um herauszufinden, wie lang denn nun eine Zeichenkette oder eine Liste ist, hat Python eine eingebaute Funktion len(), die wir befragen können:

>>> len(z)
18
>>> len(l)
5

len() gibt also die Länge (nicht den letzten Index) aus. Damit ergibt sich für den letzten Index einer Liste oder Zeichenkette der Wert \(Länge - 1\) :

>>> l[-1] == l[len(l) - 1]
True

Ein kleines Beispiel #

Tippe einmal folgenden Code in Thonny ab, und lass ihn laufen.

liste = [None] * 101

i = 0

while i < len(liste):
    liste[i] = i * i
    i += 1

for zahl in liste:
    print(zahl)

Kannst Du Dir vorstellen, was hier passiert?

Mit liste = [None] * 101 wird eine Liste erstellt, die 101 Mal mit dem Wert None (das steht in Python für Nichts) gefüllt wird. Der Index des ersten Listenplatzes ist 0, und der Index des letzten Listenplatzes ist 100.

Mit i = 0 wird eine Variable i, die es vorher noch nicht gab, auf 0 gesetzt. (Programmier_innen sagen dazu: »i wird mit dem Wert 0 initialisiert.«) Wie du vielleicht schon weißt, verstehen Programmiererinnen und Programmierer ganz schnell, um was es geht, wenn eine Variable i, j oder auch einmal k heißt – das sind Zählvariablen!

Nun beginnt mit der Zeile while i < len(liste): die while-Wiederholung: alles, was nun eingerückt aufgeschrieben ist, wird so lange wiederholt, bis die Bedingung i < len(liste) nicht mehr zu True, sondern zu False ausgewertet wird. (Dass diese Bedingung irgendwann mal False werden musst, weißt du schon – wäre das nicht der Fall, würde die Wiederholung bis in alle Ewigkeit laufen…)

Die erste Zeile des Wiederholungsblocks trägt nun einen neuen Wert an einem bestimmten Listenplatz ein. Beim ersten Mal ist unser i gleich 0, daher ist das die Position 0, und der Wert wird auf i * i, also 0 mal 0 (das ist wieder 0) gesetzt:

0 1 2 3 4 5
0 None None None None None

In der nächsten Zeile i += 1 wird zu dem Wert von i (das ist beim ersten Mal 0) eins hinzugezählt, und der neue Wert (das ist dann eins) wieder in i abgespeichert. (Statt der kurzen Schreibweise könnte man auch i = i + 1 schreiben.) Das wird so lange wiederholt, bis i nicht mehr kleiner ist als die Länge der Liste (die Bedingung unserer while-Wiederholung). Schließlich sieht die Liste (hier nur der Anfang davon) dann so aus:

0 1 2 3 4 5
0 1 4 9 16 25

Herzlichen Glückwunsch! Du hast gerade in sehr kurzer Zeit sehr viele Quadratzahlen ausgerechnet!

Aufgabe: ASCII-Art #

Hier findest Du ein kleines Programm für ein Text-Adventure, das den Namen einer Kneipe etwas anschaulicher darstellen soll, z.B. so:

----
 |L|
 |o|
 |u|
 |n|
 |g|
 |e|
----

Das Programm dazu sieht so aus:

def barschild(bar_name):
    laenge = len(bar_name)
    print('----')
    
    for i in range(laenge):
        s = ' |' + bar_name[i] + '|'
        print(s)
    
    print('----')

deine_bar = input('Wie soll die Bar heißen? ')
barschild(deine_bar)

Übernimm diesen Code in ein neues Thonny-Projekt. (Abtippen ist eine gute Idee – da bleibt es besser im Kopf!) Lass das Programm laufen und vollziehe es nach. Probiere auch den Debug-Modus aus, indem Du auf den Käfer klickst, und dann wiederholt F7 drückst!

Ersetze in der Funktion barschild dann die for-Wiederholung durch eine while-Wiederholung.

Lösungsvorschlag
def barschild(bar_name):
    laenge = len(bar_name)
    print('----')
    
    i = 0
    while i < laenge:
        s = ' |' + bar_name[i] + '|'
        print(s)
        i += 1
    
    print('----')

deine_bar = input('Wie soll die Bar heißen? ')
barschild(deine_bar)

Zurück Weiter