Strings
Zeichenketten
Einer der wichtigsten Datentypen ist die Zeichenkette, auch als String bezeichnet. Programme lesen Eingaben von der Tastatur, die als Strings verarbeitet werden müssen oder erzeugen Ausgaben auf dem Bildschirm, die ebenfalls Strings sind. Ein signifikanter Anteil der Programmierung geht deshalb in die Stringverarbeitung.
Strings (Zeichenketten)
- sind eine Sequenz von Zeichen (→ Listen)
- sind unveränderlich
- können wie Listen und Tupel "gesliced" werden
- stehen zwischen einfachen (
') oder doppelten Anführungszeichen (")
s1 = 'Hallo, Welt!'
s2 = "Hola el mundo!"
s1[7:] # -> 'Welt!'
s2[0:4] # -> 'Hola'
Python-Strings werden als Kette von einzelnen Zeichen aufgefasst. Ein Zeichen in einem String kann hierbei jedes Unicode-Zeichen sein; wir sind also nicht auf die 127 Zeichen des US-ASCII-Zeichensatzes beschränkt.
Ein wichtiger Unterschied zu den Liste ist, dass Strings unveränderlich sind. Nach seiner Erzeugung kann man einen String nicht mehr abändern.
s = "Hallo"
s[1] = "o" # TypeError: 'str' object does not support item assignment
Analog zu den Listen kann man aber Strings slicen, d. h. Sub-Strings erzeugen.
s = "Hallo Python-Programmierung"
print(s[-21:]) # -> Python-Programmierung
print(s[:5]) # -> Hallo
Durch das Slicen entsteht ein neues, wieder unveränderliches String-Objekt.
Es gibt keinen besonderen Unterschied zwischen den beiden unterschiedlichen Begrenzern ' und ". Python unterstützt zwei verschiedene Zeichen, damit man leichter Anführungszeichen innerhalb Strings verwenden kann, indem man das jeweils andere als Begrenzer verwendet.
s1 = 'Thomas sagte "Python rocks".'
s2 = "Thomas' Idee war es nicht."
Intern bezeichnet Python den Datentyp für Strings als str.
print(type("ich bin ein String")) # -> <class 'str'>
Wir haben bereits bei den Sets gesehen, dass in Python Operatoren überladen werden können, d. h. auch für nicht-numerische Datentypen eingesetzt werden können. Für Strings ist der +-Operator so umdefiniert, dass er zwei Strings verkettet.
- Strings können mit
+verkettet werden
s1 = "Hallo"
s2 = ", "
s3 = "Welt"
ergebnis = s1 + s2 + s3 + "!"
print(ergebnis) # -> Hallo, Welt!
print(s1) # -> Hallo
Bei der Stringverkettung entsteht ein neuer String, die ursprünglichen Strings (s1, s2 und s3 im Beispiel) bleiben unverändert.
Beim +-Operator müssen beide Operanden Strings sein.
s = "Hallo"
ergebnis = s + 3 # Fehler
# TypeError: can only concatenate str (not "int") to str
Ein weiterer Operator, der bei Strings eine besondere Bedeutung hat, ist der *-Operator. Er dient dazu, die Zeichen eines Strings n-Mal zu wiederholen.
- Strings können mit
*wiederholt werden
chicken = "chicken " * 5
print(chicken)
chicken chicken chicken chicken chicken
Anders als bei dem +-Operator muss hier einer der Operanden eine Ganzzahl sein. Hierbei ist es egal, ob zuerst die Zahl und dann der String kommt oder umgekehrt.
s = "Hallo "
print(s * 3) # -> Hallo Hallo Hallo
print(3 * s) # -> Hallo Hallo Hallo
Umwandlung von/in String
Wie geht man vor, wenn man einen Datentyp hat, der kein String ist und diesen aber als String benötigt?
- Jeder Datentyp in Python kann mit der Funktion
str()in einen String umgewandelt werden - Wenn keine sinnvolle Darstellung existiert, wird der Datentyp und seine Adresse ausgegeben
t = ('a', 'b', 'c')
s = str(t) # -> "('a', 'b', 'c')"
s[0:3] # -> "('a"
n = 42
s = str(n) # -> '42'
str() funktioniert immer, liefert aber nicht zwangsweise sinnvolle Ergebnisse. Im folgenden Beispiel wird eine eigene Klasse X definiert und davon wird ein Objekt angelegt. Verfüttert man dieses an die str()-Methode bekommt man Informationen zu Typ des Objektes (X) und seiner Speicherstelle (0x7f62b4247970>). Details zu Klassen folgen im entsprechenden Kapitel.
class X:
pass
x = X()
print(str(x)) # -> <__main__.X object at 0x7f62b4247970>
Will man dieses Verhalten ändern, muss man der Klasse eine __str__-Methode spendieren.
class X:
def __str__(self):
return "Ich bin ein X ;-)"
x = X()
print(str(x)) # -> Ich bin ein X ;-)
Was hier genau passiert, brauchen Sie nicht unbedingt zu verstehen – es nur der Vollständigkeit halber gezeigt.
Bei Listen ist es nicht immer attraktiv, sie einfach mit str() in einen String umzuwandeln, weil man dann keine Kontrolle darüber hat, wie die Elemente verkettet werden.
l = ['a', 'b', 'c', 'd']
print(str(l)) # -> ['a', 'b', 'c', 'd']
Deswegen gibt es eine alternative Möglichkeit Listen mit join() in Strings umzuwandeln und dabei deutlich mehr Kontrolle über die Darstellung zu haben, weil man das Trennzeichen angeben kann.
- Listenelemente können mit
join()zu einem String zusammengesetzt werden - Syntax:
trennzeichen.join(liste)
l = ['a', 'b', 'c', 'd']
print(''.join(l)) # -> 'abcd'
print(' '.join(l)) # -> 'a b c d'
print(', '.join(l)) # -> 'a, b, c, d'
Liegen Daten in einem String vor, z. B. weil eine Tabelle mit Messwerten aus einer Textdatei gelesen wurde, dann möchte man diesen String in seine einzelnen Elemente zerlegen und in einer Liste speichern.
2.333 1.778 0.882 3.231
Für diesen Zweck bietet Python die split()-Methode an, der man (optional) ein Trennzeichen übergeben kann an dem der String aufgebrochen und in einzelne Listenelemente überführt wird. Gibt man kein Trennzeichen an, wird an Whitespaces (' ', '\n', '\t', '\r', '\f', '\v') getrennt.
- Strings können über
split()in Listen aufgeteilt werden - standardmäßig wird an Whitespace getrennt
s = "Hallo, Python.\nWie geht es dir?"
l = s.split()
print(l) # -> ['Hallo,', 'Python.', 'Wie', 'geht', 'es', 'dir?']
s = "1.3, 2.5, 1.4, 6.7"
l = s.split(', ')
print(l) # -> ['1.3', '2.5', '1.4', '6.7']
Im vorherigen Beispiel werden die Zahlenwerte per split() zwar korrekt auf eine Liste verteilt, es handelt sich aber immer noch um Strings. Deswegen muss man sie, falls sie verarbeitet werden sollen, in einem zweiten Schritt in Fließkommazahlen umwandeln. Dies kann elegant mit einer List-Comprehension erfolgen, ohne eine Schleife zu verwenden.
s = "1.3, 2.5, 1.4, 6.7"
l = s.split(', ')
n = [float(i) for i in l]
print(n) # -> [1.3, 2.5, 1.4, 6.7]
Man kann die Umwandlung auch in einem einzigen Schritt machen.
s = "1.3, 2.5, 1.4, 6.7"
n = [float(i) for i in s.split(', ')]
print(n) # -> [1.3, 2.5, 1.4, 6.7]
Escape-Sequenzen
Nicht alle Zeichen, die man ausgeben möchte, kann man einfach in einem Quelltext darstellen, z. B. das Zeichen für eine neue Zeile oder einen Tabulator. Ein anderes Problem sind die Zeichen " und ' die als Stringbegrenzer dienen und deswegen nicht in einem String vorkommen können, der durch sie begrenzt wird.
Damit man diese Zeichen trotzdem in Stringliteralen verwenden kann, gibt es sogenannte Escape Sequenzen, die mit einem Backslash \ beginnen und dann das Zeichen definieren, das an Stelle ihrer eingesetzt werden soll. Durch das Escape-Zeichen \ bekommt das nächste Zeichen eine spezielle Bedeutung. Da der Backslash ebenfalls zu einem speziellen Zeichen wird, muss man ihn durch \\ darstellen.
Strings können spezielle Zeichen enthalten (Escape Sequenzen)
\\- Backslash\n- Neue Zeile (newline)\f- Seitenvorschub (form feed)\r- Wagenrücklauf (carriage return)\v- Vertikaler Tabulator\b- Backspace (löscht Zeichen links)\t- Tabulator\',\"- Anführungszeichen
print('c:\\windows')
print('vor newline\nnach newline')
print('vor formfeed\fnach formfeed')
print('a\tb')
print('vor\bnach')
print('Ich habe einen 26\'7" Monitor')
c:\windows
vor newline
nach newline
vor formfeed
nach formfeed
a b
vonach
Ich habe einen 26'7" Monitor
String-Formatierung
Will man Daten ausgeben, kann die Konvertierung mit str() und das Verketten mit + umständlich werden. Insbesondere, wenn man die Daten noch in einem speziellen Format darstellen möchte, z. B. bei Fließkommazahlen nur eine begrenzte Anzahl von Nachkommastellen.
f = 0.23
s = 'Hello'
i = 12
ausgabe = "s: " + s + " f: " + str(f) + " i: " + str(i)
print(ausgabe) # -> s: Hello f: 0.23 i: 12
Um diese Art von Ausgaben zu vereinfachen, bietet Strings über die format()-Methode die Möglichkeit mit Platzhaltern zu arbeiten, die im String durch Werte ersetzt werden.
- Formatierung von Strings über
format() - Platzhalter (
{}) werden durch Daten in der Parameterliste ersetzt - Ersetzung erfolgt von links nach rechts
f = 0.23
s = 'Hello'
i = 12
print("s: {} f: {:0.1f} i: {}".format(s, f, i))
s: Hello f: 0.2 i: 12
In den Platzhaltern ({}) können Anweisungen untergebracht werden, wie die Daten einzufügen sind, so sorgt z. B. {:0.1f} dafür, dass der Wert als Fließkommazahl mit nur einer Nachkommastelle ausgegeben wird. Die verschiedenen Möglichkeiten hier zu erläutern geht zu weit, sodass auf die Dokumentation verwiesen sei.
Eine weitere Möglichkeit, Strings zu formatieren, besteht darin, die Werte von Variablen direkt in den String zu übernehmen. Damit es nicht zu Fehler kommt, muss man Python explizit dazu anweisen, diese Ersetzungen zu machen, indem man den String durch ein vorangestelltes f als Format-String kennzeichnet.
Format-Strings erlauben es, Variablen direkt im Text zu ersetzen
- werden mit
f"..."deklariert - Variablen stehen in geschweiften Klammern
{name}
dozent = "Smits"
hs = "Mannheim"
print(f"{dozent} lehrt an der Hochschule {hs}")
Smits lehrt an der Hochschule Mannheim
Die Variablen können von einem beliebigen Typ sein, sie werden über die str()-Funktion umgewandelt:
pi = 3.1
print(f"Hier ist pi einfach {pi}")
# -> Hier ist pi einfach 3.1
Weitere Operationen für Strings
Es gibt noch eine Reihe von Methoden, die man auf einem String aufrufen kann, um ihn zu verändern.
upper()– in Großbuchstaben umwandelnlower()– in Kleinbuchstaben umwandelnstrip()– Leerzeichen entfernencount(x)– Anzahl der Zeichen xreplace(a, b)– ersetzeadurchb- und viele mehr…
'Hallo'.upper() # -> 'HALLO'
'Hallo'.lower() # -> 'hallo'
' Hallo '.strip() # - > 'Hallo'
'Hallo'.count('l') # -> 2
'Hallo'.replace('o', '0') # -> 'Hall0'
Neben den Methoden gibt es noch Funktionen und Operatoren, die für Strings eingesetzt werden können.
len(s)– Länge des Stringss1 == s2– Testet, ob die Strings gleich sinds1 in s2– Testet, obs1ins2vorkommt
s = "Hallo"
len(s) # -> 5
"ll" in s # -> true
"a" in s # -> true
"x" in s # -> false
"Hallo" == s # -> true
" Hallo " == s # -> false