Bei typischen Informatik-Begriffen wie „Datenverarbeitung“ oder auch „Rechner“ denkt man womöglich als Erstes an das Rechnen mit Zahlen. Tatsächlich machen aber, quantitativ gesehen, numerische Daten nur einen kleinen Teil der Daten aus, die wir mit Computern verarbeiten können. Viele Informationen liegen in Form von geschrieben Texten vor, die von unseren Programmen ausgewertet werden. In diesem Kapitel geht es um Text-Daten, die sogenannten Zeichenketten. Wir werden sehen, wie man in Python Zeichenketten anlegt und vor allem, wie man mit ihnen umgehen kann.
Noch einen kleinen Tipp vorab: vieles von dem, was man mit Zeichenketten machen kann, funktioniert genau so mit Folgen von völlig andren Elementen. Wenn Sie in diesem Kapitel genau hinsehen, kommt Ihnen das also in den folgenden umso mehr zugute.
\index{Folge} \index{Einzelzeichen}\index{Character}
Eine Zeichenkette (englisch String) ist eine Folge einzelner Zeichen (englisch Character). Wir können die Folge von Zeichen einfach „wie Text“ im Programm angeben. Wichtig ist nur, dass sie in Anführungszeichen gesetzt wird, denn sonst würde Python die Zeichen als Bezeichner (also z. B. als Variable) deuten.
Python lässt übrigens sowohl einfache ('...'
), als auch die im Deutschen verwendeten doppelten ("..."
) Anführungszeichen zu. Es macht also keinen Unterschied, ob Sie die Zeichenkette als 'Hallo Welt'
oder als "Hallo Welt"
angeben.
Auf den ersten Blick erscheint es überflüssig zu sein, zwei Schreibweisen für den gleichen Zweck zu haben. Es gibt aber mindestens ein gutes Gegenargument: Stellen Sie sich vor, sie möchten ein Anführungszeichen (egal ob doppelt oder einfach) in einer Zeichenkette verwenden. Python erlaubt es nun, dass Sie dasjenige Anführungszeichen zum Einfassen der Zeichen verwenden, dass Sie in der Zeichenkette nicht benötigen.
>>> text1 = 'Sie rief ihnen "Hallo" zu.'
>>> text2 = "Hello it's me"
>>> text3 = 'What\'s up?'
text1
verwendet einfache Anführungszeichen, um im Satz die wörtliche Rede „Hallo“ in doppelten Anführungszeichen darstellen zu können. In text2
verwenden wir doppelten Anführungszeichen, da wir im Text ein Apostroph setzen wollen. text3
verwendet nur einfach Anführungszeichen, obwohl im Text ein Apostroph vorkommt. Wir müssen dieses Apostrophzeichen mit einem sogenannten Maskierungszeichen versehen. Python verwendet hier, wie die meisten Programmiersprachen den Backslash \
. Dieses Sonderzeichen verhindert, dass das nachfolgende Zeichen vom ausführenden Programm als Funktionszeichen gesehen wird. Der Apostroph soll hier also nicht den String schließen, sondern als wirklicher Apostroph in der Zeichenkette erscheinen.
Es steht Ihnen also frei, einfache oder doppelten Anführungszeichen zu verwenden. Die Konvention, die sich bei vielen Python-Programmierern eingebürgert hat, ist einfache Anführungszeichen für einzelne Worte oder Begriffe zu verwenden und doppelte Anführungszeichen für ganze Sätze.
Da eine Zeichenkette eine Folge (einzelner) Zeichen ist, können wir auch auf die einzelnen Elemente dieser Folge zugreifen. Dies funktioniert mit dem indexbasierten Zugriffsoperator (auch Klammeroperator genannt):
\index{Indexoperator}\index{Zugriff, indexbasiert} \index{Operator!indexbasierter Zugriff}
>>> frucht = 'Banane'
>>> zeichen = frucht[1]
\index{Index} \index{}
Die zweite Anweisung extrahiert das Zeichen an Indexposition 1 aus der Variablen frucht
und weist es der Variablen zeichen
zu.
Der Ausdruck in eckigen Klammern wird als Index bezeichnet. Der Index gibt an, auf welches Zeichen in der Sequenz zugegriffen werden soll. Aber wir bekommen vielleicht nicht das, was wir erwarten:
>>> print(zeichen)
a
Für die meisten Menschen ist der erste Buchstabe von „Banane“ eigentlich ein „B“, aber nicht „a“. Aber in Python ist der Index ein Offset vom Anfang der Zeichenkette, und der Offset des ersten Buchstabens ist 0.
>>> zeichen = frucht[0]
>>> print(zeichen)
B
So ist „B“ der nullte Buchstabe von „Banane“, „a“ der erste und „n“ der zweite Buchstabe.
\index{Index!beginnt mit Null} \index{Null, Index beginnt mit}
Man kann einen beliebigen Ausdruck, einschließlich Variablen und Operatoren, als Index verwenden, aber der Wert des Index muss eine ganze Zahl sein. Sonst erhält man:
\index{Index} \index{} \index{Ausnahme!TypeError} \index{TypeError}
>>> zeichen = frucht[1.5]
TypeError: string indices must be integers
\index{len (Funktion)} \index{Funktion!len}
len
ist eine eingebaute Funktion, die die Anzahl der Zeichen in einer Zeichenkette zurückgibt:
>>> frucht = 'Banane'
>>> len(frucht)
6
Um den letzten Buchstaben einer Zeichenkette zu erhalten, könnte man versucht sein, etwas wie das hier zu tun:
\index{Ausnahme!IndexError} \index{IndexError}
>>> length = len(frucht)
>>> last = frucht[length]
IndexError: string index out of range
Der Grund für den IndexError
ist, dass es keinen Buchstaben in „Banane“ mit dem Index 6 gibt. Da wir bei null angefangen haben zu zählen, sind die sechs Buchstaben von 0 bis 5 nummeriert. Um das letzte Zeichen zu erhalten, müssen wir 1 von length
subtrahieren:
>>> last = frucht[length-1]
>>> print(last)
e
Alternativ können wir auch negative Indizes verwenden, die vom Ende der Zeichenkette rückwärts zählen. Der Ausdruck frucht[-1]
ergibt den letzten Buchstaben, frucht[-2]
den vorletzten und so weiter.
\index{Index!negativ} \index{negativer Index}
\index{Traversieren} \index{Schleife!Traversieren} \index{for-Schleife} \index{Schleife!for} \index{Traversieren}
Bei vielen Berechnungen wird eine Zeichenkette Zeichen für Zeichen verarbeitet. Oft beginnen sie am Anfang, wählen jedes Zeichen der Reihe nach aus, machen etwas damit und fahren bis zum Ende fort. Dieses Verarbeitungsmuster wird als Traversierung bezeichnet. Eine Möglichkeit, eine solche Traversierung zu implementieren, ist eine while
-Schleife:
index = 0
while index < len(frucht):
zeichen = frucht[index]
print(zeichen)
index = index + 1
Diese Schleife durchläuft die Zeichenkette und zeigt jeden Buchstaben einzeln in einer Zeile an. Die Schleifenbedingung ist index < len(frucht)
, wenn also index
gleich der Länge der Zeichenkette ist, ist die Bedingung falsch und der Schleifenrumpf wird nicht mehr ausgeführt. Das letzte Zeichen, auf das zugegriffen wird, ist dasjenige mit dem Index len(frucht)-1
, also das letzte Zeichen in der Zeichenkette.
Übung 1: Schreiben Sie eine while
-Schleife, die beim letzten Zeichen in der Zeichenkette beginnt und sich rückwärts bis zum ersten Zeichen in der Zeichenkette vorarbeitet, wobei jeder Buchstabe in einer eigenen Zeile ausgegeben wird, natürlich rückwärts.
Eine andere Möglichkeit, einen Traversierung zu schreiben, ist mit einer for
-Schleife:
for char in frucht:
print(char)
Jedes Mal, wenn die Schleife durchlaufen wird, wird das nächste Zeichen in der Zeichenkette der Variablen char
zugewiesen. Die Schleife wird fortgesetzt, bis keine Zeichen mehr übrig sind.
\index{slice-Operator} \index{Operator!slice} \index{Index!slice} \index{Zeichenkette!slice} \index{slice!Zeichenkette}
Ein Segment einer Zeichenkette wird im Englischen als Slice oder Substring (deutsch Teilzeichenkette) bezeichnet. Die Auswahl einer Teilzeichenkette funktioniert ähnlich wie die Auswahl eines Zeichens:
>>> s = 'Monty Python'
>>> print(s[0:5])
Monty
>>> print(s[6:12])
Python
Der Operator gibt den Teil der Zeichenkette vom n-ten Zeichen bis zum m-ten Zeichen zurück, einschließlich des ersten, aber ausschließlich des letzten Zeichens.
Die erste print
-Anweisung im obigen Beispiel druckt also die Zeichen 0 bis 4 des Strings, das zweite print
druckt die Zeichen 6 bis 11.
Wenn man den ersten Index (vor dem Doppelpunkt) weglässt, beginnt die Teilzeichenkette am Anfang der Zeichenkette. Wenn man den zweiten Index ebenfalls weglässt, geht die Teilzeichenkette bis zum Ende der Zeichenkette:
>>> frucht = 'Banane'
>>> frucht[:3]
'Ban'
>>> frucht[3:]
'ane'
Wenn der erste Index größer oder gleich dem zweiten ist, ist das Ergebnis eine leere Zeichenkette, dargestellt durch zwei Anführungszeichen:
\index{Anführungszeichen}
>>> frucht = 'Banane'
>>> frucht[3:3]
''
Eine leere Zeichenkette enthält keine Zeichen und hat die Länge 0, aber ansonsten verhält sie sich genauso wie jede andere Zeichenkette.
Übung 2: Wenn frucht
eine Zeichenkette ist, was bewirkt dann frucht[:]
?
\index{Kopieren!slice} \index{slice!Kopieren}
\index{Veränderbarkeit} \index{Unveränderlichkeit} \index{Zeichenkette!unveränderlich}
Es ist verlockend, den Operator auf der linken Seite einer Zuweisung zu verwenden, mit der Absicht, ein Zeichen in einer Zeichenkette zu ändern. Zum Beispiel:
\index{TypeError} \index{Ausnahme!TypeError}
>>> greeting = 'Hello, world!'
>>> greeting[0] = 'J'
TypeError: 'str' object does not support item assignment
Das „Objekt“ ist in diesem Fall die Zeichenkette und das „Element“ ist das Zeichen, das wir versucht haben zuzuweisen. Im Moment ist ein Objekt dasselbe wie ein Wert, aber wir werden diese Definition später verfeinern. Ein Element ist einer der Werte in einer Sequenz.
\index{Objekt} \index{Elementzuweisung} \index{Zuweisung!Element} \index{Unveränderlichkeit}
Der Grund für den Fehler ist, dass Zeichenketten unveränderlich sind. Dies bedeutet, dass wir eine vorhandene Zeichenkette nicht ändern können. Das Beste, was wir tun können, ist, eine neue Zeichenfolge zu erstellen, die eine Variation der ursprünglichen Zeichenfolge ist:
>>> greeting = "Hello, world!"
>>> new_greeting = 'J' + greeting[1:]
>>> print(new_greeting)
Jello, world!
In diesem Beispiel wird ein neuer Anfangsbuchstabe an ein Stück von greeting
angehängt. Es hat keine Auswirkung auf die ursprüngliche Zeichenfolge.
\index{Konkatenation}
\index{Schleifenzähler} \index{Zählen mit Schleifen} \index{Schleifen und Zählen} \index{Schleife!mit Zeichenketten}\index{Iteration!durch Zeichenketten}
Das folgende Programm zählt, wie oft der Buchstabe „a“ in einer Zeichenkette vorkommt:
word = 'Banane'
count = 0
for zeichen in word:
if zeichen == 'a':
count = count + 1
print(count)
Dieses Programm demonstriert ein Vorgehen, das man als Zähler bezeichnet könnte. Die Variable count
wird mit 0 initialisiert und dann jedes Mal inkrementiert, wenn ein 'a'
gefunden wird. Wenn die Schleife beendet wird, enthält count
das Ergebnis: die Gesamtzahl der „a“.
\index{Auslagern von Code}
Übung 3: Lagern Sie diesen Code in eine Funktion namens count
aus, und verallgemeinern Sie diese so, dass sie die Zeichenkette und den Buchstaben als Argumente akzeptiert.
\index{in (Operator)} \index{Operator!in} \index{boolescher Operator} \index{Operator!boolescher}
Das Schlüsselwort in
ist ein boolescher Operator, der zwei Zeichenketten annimmt und True
zurückgibt, wenn die erste Zeichenkette als Teilzeichenkette in der zweiten erscheint:
>>> 'an' in 'Banane'
True
>>> 'anna' in 'Banane'
False
\index{Zeichenkette!Vergleich} \index{Vergleich!Zeichenkette}
Die Vergleichsoperatoren arbeiten mit Zeichenketten. Um zu sehen, ob zwei Zeichenketten gleich sind:
if word == 'Banane':
print('Genau, Banane!')
Andere Vergleichsoperationen sind nützlich, um Wörter in alphabetische Reihenfolge zu bringen:
if word < 'banane':
print('Dein Wort,' + word + ', kommt vor banane.')
elif word > 'Banane':
print('Dein Wort,' + word + ', kommt nach banane.')
else:
print('Genau, banane!')
Python geht mit Groß- und Kleinbuchstaben nicht so um, wie es Menschen tun. Alle Großbuchstaben kommen vor allen Kleinbuchstaben, also:
Dein Wort,Traube, kommt vor banane.
Eine gängige Methode, dieses Problem zu beheben, besteht darin, Zeichenketten in ein Standardformat zu konvertieren, z. B. in Kleinbuchstaben, bevor der Vergleich durchgeführt wird.
Zeichenketten sind ein Beispiel für Objekte in Python. Ein Objekt enthält sowohl Daten (in diesem Beispiel die eigentliche Zeichenkette selbst) als auch sogenannte Methoden, also Funktionen, die in das Objekt eingebaut sind und jeder Instanz des Objekts zur Verfügung stehen.
Python hat eine Funktion namens dir
, die die verfügbaren Methoden für ein Objekt auflistet. Die Funktion type
zeigt den Typ eines Objekts und die Funktion dir
seine Methoden.
>>> stuff = 'Hello world'
>>> type(stuff)
<class 'str'>
>>> dir(stuff)
['capitalize', 'casefold', 'center', 'count', 'encode',
'endswith', 'expandtabs', 'find', 'format', 'format_map',
'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit',
'isidentifier', 'islower', 'isnumeric', 'isprintable',
'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower',
'lstrip', 'maketrans', 'partition', 'replace', 'rfind',
'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip',
'split', 'splitlines', 'startswith', 'strip', 'swapcase',
'title', 'translate', 'upper', 'zfill']
Im Gegensatz zur Funktion dir
, die lediglich eine grobe Auflistung der Methoden anzeigt, liefert die Funktion help
eine vollständige Hilfe. Besonders im interaktiven Modus ist help
eine schnelle und gute Möglichkeit, um Informationen zu einer bestimmten Funktion zu erhalten. Noch übersichtlicher als help
ist die Dokumentation der Standardbibliothek im Internet unter docs.python.org.
>>> help(str.capitalize)
Help on method_descriptor:
capitalize(...)
S.capitalize() -> str
Return a capitalized version of S, i.e. make the first character
have upper case and the rest lower case.
>>>
Der Aufruf einer Methode ist ähnlich wie der Aufruf einer Funktion (sie nimmt Argumente entgegen und gibt einen Wert zurück), aber die Syntax ist anders. Wir rufen eine Methode auf, indem wir den Methodennamen an den Variablennamen anhängen und den Punkt als Begrenzer verwenden.
Zum Beispiel nimmt die Methode upper
eine Zeichenkette entgegen und gibt eine neue Zeichenkette zurück, die nur aus Großbuchstaben besteht:
\index{Methode} \index{Zeichenkette!Methode}
Anstelle der Funktionssyntax upper(word)
wird die Methodensyntax word.upper()
verwendet.
\index{Punktnotation}
>>> word = 'Banane'
>>> new_word = word.upper()
>>> print(new_word)
BANANE
Diese Form der Punktschreibweise gibt den Namen der Methode (upper
) und den Namen der Zeichenkette (word
), auf die die Methode angewendet werden soll an. Die leeren Klammern zeigen an, dass diese Methode kein Argument benötigt.
\index{Klammern!leer}
Ein Methodenaufruf wird als Aufruf bezeichnet; in diesem Fall würden wir sagen, dass wir upper
auf word
aufrufen. Die Aufrufkonvention mit der Punktnotation ist typisch für die objektorientierte Programmierung. Die Zeichenkette word
ist in diesem Fall unser Objekt, und der Aufruf der Methode upper
auf dem Objekt bewirkt, dass etwas mit dem Objekt passiert.
\index{Aufruf einer Methode}
Es gibt weitere Zeichenketten-Methoden, beispielsweise die Methode find
, die nach der Position einer Zeichenkette innerhalb einer anderen sucht:
>>> word = 'Banane'
>>> index = word.find('a')
>>> print(index)
1
In diesem Beispiel rufen wir find
auf word
auf und übergeben den gesuchten Buchstaben als Parameter.
Die Methode find
kann sowohl Teilzeichenketten als auch Zeichen finden:
>>> word.find('na')
2
Sie kann als zweites Argument den Index annehmen, bei dem sie beginnen soll:
\index{optionales Argument} \index{Argument!optional}
>>> word.find('a', 2)
3
Eine häufige Aufgabe ist das Entfernen von Whitespaces (Leerzeichen, Tabulatoren oder Zeilenumbrüche) am Anfang und Ende einer Zeichenkette mit der Methode strip
:
>>> line = ' Here we go '
>>> line.strip()
'Here we go'
Einige Methoden wie startswith
geben boolesche Werte zurück.
>>> line = 'Have a nice day'
>>> line.startswith('Have')
True
>>> line.startswith('h')
False
Man kann feststellen, dass startswith
Groß- und Kleinschreibung unterscheidet, daher nehmen wir manchmal eine Zeile und wandeln mit lower
alles in Kleinbuchstaben um, bevor wir eine Überprüfung mit der Methode startswith
durchführen.
>>> line = 'Have a nice day'
>>> line.startswith('h')
False
>>> line.lower()
'have a nice day'
>>> line.lower().startswith('h')
True
Im letzten Beispiel wird die Methode lower
aufgerufen und dann wird mit startswith
geprüft, ob die resultierende klein geschriebene Zeichenkette mit dem Buchstaben „h“ beginnt. Solange wir mit der Reihenfolge vorsichtig sind, können wir mehrere Methodenaufrufe in einem einzigen Ausdruck machen.
\index{count (Methode)} \index{Methode!count}
Übung 4: Es gibt eine String-Methode namens count
, die der Funktion in der vorherigen Übung ähnlich ist. Lesen Sie die Dokumentation zu dieser Methode unter:
https://docs.python.org/library/stdtypes.html#string-methods
Schreiben Sie ein Programm, das die Anzahl der Vorkommen des Buchstabens „a“ in „Banane“ mithilfe der count-Methode zählt.
Oft wollen wir in eine Zeichenkette schauen und eine Teilzeichenkette finden. Wenn wir zum Beispiel eine Liste von Zeilen erhalten, die wie folgt formatiert sind:
From giefers.heiner@
*fh-swf.de
* Mon, 30 Aug 2021 16:20:09
Wollten wir nur die Domäne der e-Mail Adresse (d. h. fh-swf.de
) aus jeder Zeile extrahieren, können wir dies mit der Methode find
und String-Slicing erreichen.
Zuerst wird die Position des at-Zeichens in der Zeichenkette ermittelt. Dann werden wir die Position des ersten Leerzeichens nach dem at-Zeichen finden. Und dann verwenden wir String-Slicing, um den Teil der Zeichenkette zu extrahieren, den wir suchen.
>>> data = 'From giefers.heiner@fh-swf.de Mon, 30 Aug 2021 16:20:09'
>>> atpos = data.find('@')
>>> print(atpos)
19
>>> sppos = data.find(' ',atpos)
>>> print(sppos)
29
>>> host = data[atpos+1:sppos]
>>> print(host)
fh-swf.de
>>>
Wir verwenden eine Version der Methode find
, die es uns erlaubt, eine Position in der Zeichenkette anzugeben, an der find
mit der Suche beginnen soll. Dann extrahieren wir die Teilzeichenkette beginnen nach dem at-Zeichen bis hin (aber nicht einschließlich) zum Leerzeichen.
Die Dokumentation für die Methode find
ist verfügbar unter
https://docs.python.org/library/stdtypes.html#string-methods.
\index{Format-String} \index{Formatierungszeichen}
Wir haben nun schon mehrfach print
-Anweisungen verwendet, bei denen wir sowohl Zeichenketten als auch die Werte bestimmter Variablen ausgegeben haben. Also z. B. so:
>>> count = 2
>>> zeichen = 'a'
>>> print('Buchstabe:', zeichen, 'Anzahl:', count)
Buchstabe: a Anzahl: 2
Das funktioniert, weil die print
-Funktion eine Liste von Argumenten akzeptiert. Die Schreibweise mit den Kommas ist aber nicht gerade praktisch und auch nicht sehr übersichtlich.
Eine Abhilfe schaffen hier formatierte Zeichenketten, in Python auch Format Strings (oder f-Strings) genannt. Eine „normale“ Zeichenkette wird zu einem f-String, indem wir Ihr ein f
direkt vor dem öffnenden Anführungszeichen voranstellen. In einem f-String können wir dann Werte einbetten, indem wir die Variablennamen in geschweifte Klammern direkt in den String schreiben.
>>> count = 2
>>> zeichen = 'a'
>>> print(f'Buchstabe: {zeichen} Anzahl: {count}')
Buchstabe: a Anzahl: 2
In Format Strings erkennt man die eingebetteten Variablen sehr schnell durch die geschweiften Klammern. Gleichzeitig benötigt man keine zusätzlichen Kommas oder schließenden und öffnenden Anführungszeichen.
Ein weiterer Vorteil von Format Strings ist, dass man die Darstellungsweise der Variablen beeinflussen kann. Das ist z. B. nützlich, wenn man Fließkommazahlen ausgeben möchte. Im folgenden Beispiel berechnen wir 10/3
was in einen Wert mit unendlich vielen Nachkommastellen resultiert^[Natürlich kann kein Computer dieser Welt reelle Zahlen genau abspeichern. Intern werden reelle Werte mit einer bestimmten Genauigkeit gespeichert, die auch in Berechnungen immer wieder zu Rundungsfehlern führen. Mit diesen Fragestellungen beschäftigt sich die Computer-Arithmetik, wir werden das Thema hier nicht genauer beleuchten. Allerdings sieht man die Auswirkungen auch im täglichen Umgang mit Python. Achten Sie mal auf die letzte Ziffer bei der Darstellung von 10/3 als Kommazahl.].
>>> anteil = 10/3
>>> print("Ihr Anteil ist", anteil)
Ihr Anteil ist 3.3333333333333335
>>> print(f"Ihr Anteil ist {anteil:.2f}")
Ihr Anteil ist 3.33
Bei der Ausgabe wirkt die Darstellung so vieler Nachkommastellen häufig störend. Daher verwenden wir in der zweiten print
-Anweisung des Beispiels einen f-String. Wir betten die Variable anteil
ein, fügen aber direkt hinter dem Variablennamen noch ein Doppelpunkt ein. Danach steht ein Formatierungscode, in diesem Fall .2f
. Das bedeutet, „stelle den Wert als Fließkommazahl mit zwei Nachkommastellen dar“.
Es gibt noch weitere Codes, mit denen die Ausgabe von Werten beeinflusst werden kann.Mit dem Formatierungszeichen d
gibt man an, dass ein wert als Dezimalzahl (also „ganz normal“) formatiert werden soll. Ein o
(o
steht für „octal“) bewirkt eine Formatierung im Okatalsystem (also zur Basis 8), ein x
(x
steht für „hexadecimal“) stellte einen Wert im Hexadedezimalsystem (also zur Basis 16) dar.
>>> wert = 42
>>> print(f"Der Wert {wert:d} zur Basis 8: {wert:o} \
und zur Basis 16: {wert:x}")
Der Wert 42 zur Basis 8: 52 und zur Basis 16: 2a
Die Möglichkeiten, Darstellungsweisen mit Formatierungcodes zu verändern, sind sehr vielfältig und etwas kompliziert. Es ist also ratsam, sich eine Hilfe-Seite zur Hand zu nehmen, wenn man eine bestimmte Ausgabe erreichen möchte. Weiters zu dem Thema finden sie unter
https://docs.python.org/3/reference/lexical_analysis.html#f-strings
\index{Debugging}
Eine Fähigkeit, die man beim Programmieren kultivieren sollte, ist, sich immer zu fragen: „Was könnte hier schiefgehen?“ oder alternativ: „Welche verrückte Sache könnte unser Benutzer tun, um unser (scheinbar) perfektes Programm zum Absturz zu bringen?“.
Schauen wir uns zum Beispiel das Programm an, das wir zur Demonstration der while
-Schleife im Kapitel über Iteration verwendet haben:
\VerbatimInput{../code3/copytildone2.py}
Beobachten wir, was passiert, wenn der Benutzer eine leere Eingabezeile eingibt:
> hello there
hello there
> # don't print this
> print this!
print this!
>
Traceback (most recent call last):
File "copytildone.py", line 3, in <module>
if line[0] == '#':
IndexError: string index out of range
Der Programm funktioniert gut, bis ihm eine leere Zeile präsentiert wird. Dann gibt es kein Zeichen an der nullten Indexposition, also erhalten wir einen Traceback. Es gibt zwei Lösungen, um Zeile drei „sicher“ zu machen, auch wenn die Zeichenkette leer ist.
Eine Möglichkeit ist, einfach die Methode startswith
zu verwenden, die False
zurückgibt, wenn die Zeichenkette leer ist.
if line.startswith('#'):
\index{Wächter-Muster} \index{Muster!Wächter}
Eine andere Möglichkeit ist, die if
-Anweisung mit einem „Wächter“ abzusichern und sicherzustellen, dass der zweite logische Ausdruck nur ausgewertet wird, wenn mindestens ein Zeichen in der Zeichenkette vorhanden ist:
if len(line) > 0 and line[0] == '#':
Schleifenzähler : Eine Variable, die zum Zählen von etwas verwendet wird und normalerweise mit 0 initialisiert ist und dann inkrementiert wird. \index{Schleifenzähler}
leere Zeichenkette : Eine Zeichenkette ohne Zeichen und mit der Länge 0, dargestellt durch zwei Anführungszeichen. \index{leere Zeichenkette}
Formatierungsoperator
: Der Operator %
, der einen Format-String und ein Tupel entgegennimmt und eine Zeichenkette erzeugt, die die Elemente des Tupels enthält, die gemäß des Format-Strings formatiert sind.
\index{Formatierungsoperator}
\index{Operator!Formatierung}
Formatierungszeichen
: Ein Zeichen in einem Format-String, z. B. %d
, das angibt, wie ein Wert formatiert werden soll.
\index{Formatierungszeichen}
Format-String : Eine Zeichenkette, die mit dem Formatierungsoperator verwendet wird und Formatierungszeichen enthält. \index{Format-String}
Flag : Eine boolesche Variable, die anzeigt, ob eine Bedingung wahr oder falsch ist. \index{Flag}
Aufruf einer Methode : Eine Anweisung, die eine Methode aufruft. \index{Aufruf einer Methode}
Unveränderlichkeit : Die Eigenschaft einer Sequenz, deren Elemente nicht verändert werden können. \index{Unveränderlichkeit}
Index : Ein ganzzahliger Wert, der verwendet wird, um ein Element in einer Sequenz auszuwählen, z. B. ein Zeichen in einer Zeichenkette. \index{Index} \index{}
Element : Einer der Werte in einer Sequenz. \index{Element}
Methode : Eine Funktion, die mit einem Objekt verknüpft ist und in Punktschreibweise aufgerufen wird. \index{Methode}
Objekt : Etwas, auf das sich eine Variable beziehen kann. Im Moment können wir „Objekt“ und „Wert“ noch austauschbar verwenden. \index{Objekt}
Suche : Ein Muster, das beim Traversieren durch eine Zeichenkette dafür sorgt, dass die Suche beendet wird, sobald die gesuchte Teilzeichenkette gefunden wurde. \index{Suchmuster} \index{Muster!Suche}
Folge : Eine geordnete Menge, d. h. eine Menge von Werten, bei der jeder Wert durch einen ganzzahligen Index gekennzeichnet ist. \index{Folge}
Teilzeichenkette : Ein Teil einer Zeichenkette, der durch einen Bereich von Indizes angegeben wird. \index{Teilzeichenkette}
Traversieren : Durch die Elemente einer Sequenz iterieren und für jedes Element eine ähnliche Operation ausführen. \index{Traversieren}
Übung 5: Nehmen Sie den folgenden Python-Code, der eine Zeichenkette speichert:
str = 'X-DSPAM-Confidence: 0.8475'
Verwenden Sie find
und String-Slicing, um den Teil der Zeichenkette nach dem Doppelpunkt zu extrahieren, und verwenden Sie dann die Funktion float
, um die extrahierte Teilzeichenkette in eine Fließkommazahl zu konvertieren.
\index{Zeichenkette!Methode} \index{Methode!Zeichenkette}
Übung 6: Lesen Sie die Dokumentation der String-Methoden unter
https://docs.python.org/library/stdtypes.html#string-methods
Vielleicht möchten Sie mit einigen von ihnen experimentieren, um sicherzustellen, dass Sie verstehen, wie sie funktionieren. strip
und replace
sind besonders nützlich.
Die Dokumentation verwendet eine Syntax, die verwirrend sein kann. Zum Beispiel in find(sub[, start[, end]])
zeigen die Klammern optionale Argumente an. Also ist sub
erforderlich, aber start
ist optional, und wenn Sie start
verwenden, dann ist end
wiederum optional.