Strings

Sequenzen von Zeichen

Strings sind Zeichenketten, also Sequenzen von Zeichen.

Die Länge der Sequenz ermitteln

Die Zahl der Element in der Sequenz (also die Zahl der Zeichen) kann mit der Funktion len() ermittelt werden:


In [ ]:
satz = 'Ein String ist eine Zeichenkette.'
len(satz)

Adressierung einzelner Elemente

Jedes Element in der Sequenz kann einzeln addressiert werden:

Dabei ist zu beachten, dass das erste Element der Sequenz den Index 0 hat!


In [ ]:
# Für die folgenden Beispiele ist ein kurzer String übersichtlicher
satz = "Ein String"
satz[0]

Ausprobieren

Was passiert, wenn ich auf satz[10] zugreife?


In [ ]:

Slicing: Herausschneiden eines Substrings

Durch Angabe zweier, durch einen Doppelpunkt getrennter Werte (Index des ersten herauszuschneidenden und des ersten nicht mehr herauszuschneidenden Elements) kann man aus einem String einen Teilstring extrahieren:


In [ ]:
satz[0:3]

Ist der erste Wert 0, kann dieser weggelassen werden:


In [ ]:
satz[:3]

Wird der zweite Wert weggelassen, ist das gleichbedeutend mit "bis zum Ende des Strings":


In [ ]:
satz[3:]

Stringende

In den meisten Programmiersprachen muss man auf das letzte Elemente eines Strings so zugreifen:


In [ ]:
satz[len(satz)-1]

In Python gibt es dazu eine elegante Alternative: Man kann negative Zahlen verwenden, um von hinten her auf einzelne Zeichen zuzugreifen:

Das letzte Zeichen des Strings hat als den Index -1, das vorletzte -2 usw.


In [ ]:
satz[-1]

Übung 1

Schreiben wir ein Programm, das

  1. Zur Eingabe eines Namens auffordert
  2. Diese Eingabe in einer Variable zuweist
  3. Folgende Ausgabe produziert: "Dein Name ist XXX und besteht aus n Zeichen. Er beginnt mit X und endet mit Y. Von hinten gelesen lautet er XXX.

In [ ]:
output = ('Dein Name ist {} und besteht aus {} Zeichen. '
          'Er beginnt mit {} und endet mit {}. Von hinten gelesen lautet er {}.')

Die for-Schleife

Beim Programmieren muss häufig ein Anweisung oder eine Reihe von Anweisungen wiederholt werden, beispielsweise für jedes Element einer Sequenz (z.B. für jedes Zeichen eines Strings). Für diesen Zweck ist eine for-Schleife bestens geeignet:


In [ ]:
for char in satz:
    print(char)

Dieses Konstrukt (for Element in Sequenz) funktioniert für alle Datentypen, die in der Lage sind, ein Element nach dem anderen zu liefern. Man spricht hier von einem Iterable. Solche Iterables sind in Python zahlreich, so dass auf diese Weise nicht nur durch die Zeichen eines Strings, sondern beispielsweise auch durch die Elemente einer Liste, die Zeilen einer Datei oder einfach nur durch eine Abfolge von Zahlen iteriert werden kann:


In [ ]:
for i in range(1, 11):
    print(i)

Übung

Ermitteln wir in einer Schleife die Summe aller Zahlen zwischen 1 und 50000


In [ ]:

Verschachtelte Schleifen

Man kann zwei (oder mehr - meist nicht empfehlenswert) Schleifen ineinander verschachteln. Dadurch kann man beispielsweise als Elemente aus 2 Sequenzen miteinander kombinieren:


In [ ]:
for i in range(1, 11):
    for j in range(1, 11):
        print('{} x {} = {}'.format(j, i, i * j))

Mit Dateien arbeiten

Bevor aus einer Datei gelesen oder in eine Datei geschrieben werden kann, muss diese Datei mit der Funktion open() geöffnet werden. open() erwartet mindestens ein Argument: Den Namen (evtl. mit Pfad) zur Datei:


In [ ]:
fh = open('data/vornamen/names_short.txt')

Falls nötig, kann noch das Encoding der Datei explizit angegeben werden:


In [ ]:
fh = open('data/vornamen/names_short.txt', encoding='utf-8')

Wenn wir die Datei nicht mehr brauchen, sollte sie wieder geschlossen werden, damit das Betriebssystem die Ressource wieder freigeben kann.


In [ ]:
fh.close()

Das Objekt, das die geöffnete Datei repräsentiert, bietet mehrere Möglichkeiten um auf den Inhalt zuzugreifen, darunter auch einen Iterator, den wir in einer for-Schleife nutzen können.


In [ ]:
fh = open('data/vornamen/names_short.txt', encoding='utf-8')
for line in fh:
    print(line)
fh.close()

Eine Datei in einem Context-Manager öffnen

Es ist guter Stil, eine geöffnete Datei auch wieder zu schließen. Wenn aber z.B. das Programm abstürzt, während die Datei geöffnet ist, kann die close()-Methode nicht mehr ausgeführt werden. Um solche Probleme zu vermeiden, empfiehlt sich die Verwendung eines Context-Managers:


In [ ]:
with open('data/vornamen/names_short.txt', encoding='utf-8') as fh:
    for line in fh:
        print(line)

Weitere Methoden um aus einer Datei zu lesen

read()

Die read()-Methode liest den gesamten Dateiinhalt als String ein:


In [ ]:
with open('data/vornamen/names_short.txt', encoding='utf-8') as fh:
    data = fh.read()
print(data)

readlines()

Diese Methode liest jede Zeile der Datei als Element in eine Liste ein:


In [ ]:
with open('data/vornamen/names_short.txt', encoding='utf-8') as fh:
    data = fh.readlines()
print(data)

Übung: wie viele Zeilen hat die Datei names_short.txt?


In [ ]:

Listen

Eine Liste ist ein weiterer Sequenztyp. Eine Liste enthält eine Sequenz von Elementen. Der Datentyp eines Elements ist egal, oder anders gesagt: in einer Liste können Elemente mit beliebigen Typen gespeichert werden:


In [ ]:
students = ['Otto', 'Anna', 'Maria', 'Franz']
students

In [ ]:
temperatures = [25, 28, 20, 26, 32]
temperatures

Da eine Liste so wie ein String ein Sequenztyp ist, funktionieren viele Dinge, die wir bei Strings kennengelernt haben, auch bei Listen.

Zahl der Listenelement ermitteln

Wir können die Zahl der Elemente einer Liste mit der Funktion len() ermitteln:


In [ ]:
len(students)

Einzelne Elemente adressieren

Wie bei einem String über den Index auf ein einzelnes Zeichen zugegriffen werden kann, kann bei einer Liste ein bestimmtes Element adressiert werden:


In [ ]:
students[0]

Slicing

Außerdem können Teillisten extrahiert werden:


In [ ]:
students[1:3]

Listen verändern

Im Unterschied zu Strings sind Listen nachträglich veränderbar. Wir können jederzeit neue Elemente hinzufügen. Die Mehode append(WERT) fügt ein neues Element am Ende der Liste ein:


In [ ]:
print(students)
students.append('Otto')
print(students)

Wir können aber auch Elemente an beliebiger Position einfügen:


In [ ]:
students.insert(0, 'Berta')
students

Ebenso können wir Elemente wieder entfernen. Die Methode pop() entfernt das letzte Element der Liste.


In [ ]:
next_student = students.pop()
print(next_student)
print(students)

pop() kann aber auch optional mit einem Argument aufgerufen werden: einer Zahl die dem Index des zu entfernenden Objekts entspricht:


In [ ]:
first = students.pop(0)
print(first)
students

Elemente ersetzen

Über den Index kann der Wert eines Elements der Liste jederzeit verändert werden:


In [ ]:
print(students)
students[1] = 'Berta'
print(students)

In [ ]:
with open('data/vornamen/names_short.txt', encoding='utf-8') as fh:
    lines = fh.readlines()
print(len(lines))

Mehrdimensionale Listen

Wir haben gesehen, dass eine Liste beliebige Typen enthalten kann. Dazu gehören auch Listen. Wir können also auch eine Liste von Listen erzeugen. Stellen wir uns vor, wir messen drei Mal täglich die Temperatur und möchten diese speichern. Am ersten Tag haben wir diese 3 Messungen: [17, 28, 24]. Am zweiten Tage messen wird diese Werte [18, 31, 28]. Wir haben also eine Liste pro Tag. Die einzelnen Tage (sprich: Listen) können wir wieder in ein Liste speichern:


In [ ]:
temperatures = [
    [17, 28, 24],
    [18, 31, 28],
    [20, 35, 29]
]

Wir können uns diese Temperaturen als Tabelle vorstellen: Jede Zeile repräsentiert einen Tag, jede Spalte einen Meßzeitpunkt (z.B. 6:00, 12:00, 18:00). Wie wir auf die Messwerte eines bestimmten Tages zugreifen können, haben wir schon gelernt:


In [ ]:
temperatures[1]

Da das gewählte Element wieder eine Liste ist, können wir auch auf einzelne Element zugreifen. Den ersten Messwert des zweiten Tages erhalten wir so:


In [ ]:
temperatures[1][0]

Mit Listen-Werten rechnen

Für numerische Listen (int, float) stellt Python Funktionen bereit, die auf alle Werte einer Liste angewandt werden können:

  • max(liste) ermittelt den größten vorkommenden Wert
  • min(liste) ermittelt den kleinsten vorkommenden Wert
  • sum(liste) ermittelt die Summe aller Werte

In [ ]:
max(temperatures[0])

Übung

Wie hoch ist die gemittelte Mittagstemperatur?


In [ ]:

Zeilen einer Datei in eine Liste lesen

Kehren wir zurück zu unsere Datei mit den Vornamen. Wie wir gesehen haben, liefert die Methode readlines() den Inhalt einer Datei als Liste von Zeilen:


In [ ]:
with open('data/vornamen/names_short.txt', encoding='utf-8') as fh:
    lines = fh.readlines()
print(lines)

Die String-Methoden rstrip(), lstrip() und strip()

Wie wir sehen, enthält jedes Listenelement am Ende das Zeilenumbruchszeichen \n (line feed). Wir könnten dieses z.B. mit Slicing entfernen, jedoch bietet der String-Typ eine Methode .rstrip(), die genau das tut, was wird brauchen:


In [ ]:
s = 'abc\n'
s.rstrip()

rstrip() entfernt allen Whitespace (Leerzeichen, Tabulaturen, Zeilenumbrüche etc.) am Ende einen Strings. Zusätzlich gibt es noch lstrip(), das Whitespace am Anfang eines Strings entfernt, und strip(), das Whitespace links und rechts entfernt.


In [ ]:
s = '   abc   '
print('rstrip: "{}"'.format(s.rstrip()))
print('lstrip(): "{}"'.format(s.lstrip()))
print('strip(): "{}"'.format(s.strip()))

Zeilenumbrüche in einer Liste von Strings entfernen

Methode 1: in einer Schleife

Wenn wir nun alle Zeilenumbrüche aus unserer Liste lines entfernen wollen, können wir das in einer for-Schleife tun:


In [ ]:
clean_names = []
for line in lines:
    clean_names.append(line.rstrip())
print(clean_names)

Damit haben wir auch schon die erste Listen-Methode kennengelernt, die es bei Strings (die unveränderbar sind) nicht gibt: Mit list.append(WERT) können wir der Liste einen weiteren Wert hinzufügen. Dieser Wert wird hinten an die Liste angefügt:


In [ ]:
queue = ['Anna', 'Hans', 'Berta']
queue.append('Dora')
queue

Methode 2: mit einer List Comprehension

List Comprehensions sind ein aus dem Bereich der funktionalen Programmierung kommender Ansatz, um eine Aktion auf alle Elemente eine Liste anzuwenden.


In [ ]:
clean_names = [line.rstrip() for line in lines]
print(clean_names)

Übung

Schreiben Sie eine List Comprehension, die jeden Wert der Liste nums mit sich selbst multipliziert.


In [ ]:
nums = [4, 9, 17, 5, 99]
# TODO: fertig machen

In [ ]: