Zeichenketten

Die Verarbeitung von Zeichenketten ist eine der Stärken von Python. Es gibt viele Optionen zur Begrenzung von Zeichenketten:

"Eine Zeichenfolge in doppelten Anführungszeichen kann 'einfache Anführungszeichen' enthalten."
'Eine Zeichenfolge in einfachen Anführungszeichen kann "doppelte Anführungszeichen" enthalten.'
'''\tEine Zeichenkette, die mit einem Tabulator beginnt und mit einem Zeilenumbruchzeichen endet.\n'''
"""Dies ist eine Zeichenkette in dreifach doppelten Anführungszeichen, die
einzige Zeichenkette, die echte Zeilenumbrüche enthält."""

Zeichenketten können durch einfache (' '), doppelte (" "), dreifache einfache (''' ''') oder dreifache doppelte (""" """) Anführungszeichen getrennt werden und können Tabulator- (\t) und Zeilenumbruchzeichen (\n) enthalten. Allgemein können Backslashes \ als Escape-Zeichen verwendet werden. So kann z.B. (zum Beispiel) `\`` für einen einzelnen Backslash und \" für ein einfaches Anführungszeichen verwendet werden, wodurch es die Zeichenfolge nicht beendet:

"You don't need a backslash here."
'However, this wouldn\'t work without a backslash.'

Eine normale Zeichenkette kann nicht auf mehrere Zeilen aufgeteilt werden. Der folgende Code wird nicht funktionieren:

"Dies ist ein fehlerhafter Versuch, einen einen Zeilenumbruch in
eine Zeichenkette einzufügen, ohne \n zu verwenden."

Python bietet jedoch Zeichenketten in dreifachen Anführungszeichen ("""), die dies ermöglichen und einfache und doppelte Anführungszeichen ohne Backslashes enthalten können.

Zeichenketten sind außerdem unveränderlich. Die Operatoren und Funktionen, die mit ihnen arbeiten, geben neue, vom Original abgeleitete Zeichenketten zurück. Die Operatoren (in, + und *) und eingebauten Funktionen (len, max und min) arbeiten mit Zeichenketten genauso wie mit Listen und Tupeln.

>>> welcome = "Hello pythonistas!\n"
>>> 2 * welcome
'Hello pythonistas!\nHello pythonistas!\n'
>>> welcome + welcome
'Hello pythonistas!\nHello pythonistas!\n'
>>> 'python' in welcome
True
>>> max(welcome)
'y'
>>> min(welcome)
'\n'

Die Index- und Slice-Notation funktioniert auf die gleiche Weise, um Elemente oder Slices zu erhalten:

>>> welcome[0:5]
'Hello'
>>> welcome[6:-1]
'pythonistas!'

Die Index- und Slice-Notation kann jedoch nicht verwendet werden, um Elemente hinzuzufügen, zu entfernen oder zu ersetzen:

>>> welcome[6:-1] = 'everybody!'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

string

Für Zeichenketten gibt es in der Standard-Python-Bibliothek string mehrere Methoden, um mit ihrem Inhalt zu arbeiten u.a. str.split(), str.replace() und str.strip():

>>> welcome = "hello pythonistas!\n"
>>> welcome.isupper()
False
>>> welcome.isalpha()
False
>>> welcome[0:5].isalpha()
True
>>> welcome.capitalize()
'Hello pythonistas!\n'
>>> welcome.title()
'Hello Pythonistas!\n'
>>> welcome.strip()
'Hello pythonistas!'
>>> welcome.split(' ')
['hello', 'pythonistas!\n']
>>> chunks = [snippet.strip() for snippet in welcome.split(' ')]
>>> chunks
['hello', 'pythonistas!']
>>> ' '.join(chunks)
'hello pythonistas!'
>>> welcome.replace('\n', '')
'hello pythonistas!'

Im Folgenden findet ihr einen Überblick über die häufigsten String-Methoden:

Methode

Beschreibung

str.count()

gibt die Anzahl der sich nicht überschneidenden Vorkommen der Zeichenkette zurück.

str.endswith()

gibt True zurück, wenn die Zeichenkette mit dem Suffix endet.

str.startswith()

gibt True zurück, wenn die Zeichenkette mit dem Präfix beginnt.

str.join()

verwendet die Zeichenkette als Begrenzer für die Verkettung einer Folge anderer Zeichenketten.

str.index()

gibt die Position des ersten Zeichens in der Zeichenkette zurück, wenn es in der Zeichenkette gefunden wurde; löst einen ValueError aus, wenn es nicht gefunden wurde.

str.find()

gibt die Position des ersten Zeichens des ersten Vorkommens der Teilzeichenkette in der Zeichenkette zurück; wie index, gibt aber -1 zurück, wenn nichts gefunden wurde.

str.rfind()

Rückgabe der Position des ersten Zeichens des letzten Vorkommens der Teilzeichenkette in der Zeichenkette; gibt -1 zurück, wenn nichts gefunden wurde.

str.replace()

ersetzt Vorkommen einer Zeichenkette durch eine andere Zeichenkette.

str.strip(), str.rstrip(), str.lstrip()

schneiden Leerzeichen ab, einschließlich Zeilenumbrüchen.

str.split()

zerlegt eine Zeichenkette in eine Liste von Teilzeichenketten unter Verwendung des übergebenen Trennzeichens.

str.lower()

konvertiert alphabetische Zeichen in Kleinbuchstaben.

str.upper()

konvertiert alphabetische Zeichen in Großbuchstaben.

str.casefold()

konvertiert Zeichen in Kleinbuchstaben und konvertiert alle regionsspezifischen variablen Zeichenkombinationen in eine gemeinsame vergleichbare Form.

str.ljust(), str.rjust()

linksbündig bzw. rechtsbündig; füllt die gegenüberliegende Seite der Zeichenkette mit Leerzeichen (oder einem anderen Füllzeichen) auf, um eine Zeichenkette mit einer Mindestbreite zu erhalten.

Darüber hinaus gibt es einige Methoden, mit denen die Eigenschaft einer Zeichenkette überprüft werden kann:

Methode

[!#$%…]

[a-zA-Z]

[¼½¾]

[¹²³]

[0-9]

str.isprintable()

str.isalnum()

str.isnumeric()

str.isdigit()

str.isdecimal()

str.isspace() prüft auf Leerzeichen: [ \t\n\r\f\v\x1c-\x1f\x85\xa0\u1680…].

re

Die Python-Standard-Bibliothek re enthält ebenfalls Funktionen für die Arbeit mit Zeichenketten. Dabei bietet re ausgefeiltere Möglichkeiten zur Musterextraktion und -ersetzung als string.

>>> import re
>>> re.sub('\n', '', welcome)
'Hello pythonistas!'

Hier wird der reguläre Ausdruck zunächst kompiliert und dann seine re.Pattern.sub()-Methode für den übergebenen Text aufgerufen. Ihr könnt den Auddruck selbst mit re.compile() kompilieren und so ein wiederverwendbares regex-Objekt bilden, das auf unterschiedliche Zeichenketten angewendet die CPU-Zyklen verringert:

>>> regex = re.compile('\n')
>>> regex.sub('', welcome)
'Hello pythonistas!'

Wenn ihr stattdessen eine Liste aller Muster erhalten möchtet, die dem regex-Objekt entsprechen, könnt ihr die re.Pattern.findall()-Methode verwenden:

>>> regex.findall(welcome)
['\n']

Bemerkung

Um das umständliche Escaping mit \ in einem regulären Ausdruck zu vermeiden, könnt ihr rohe String-Literale wie r'C:\PATH\TO\FILE' anstelle des entsprechenden 'C:\\PATH\\TO\\FILE' verwenden.

re.Pattern.match() und re.Pattern.search() sind eng mit re.Pattern.findall() verwandt. Während findall alle Übereinstimmungen in einer Zeichenkette zurückgibt, gibt search nur die erste Übereinstimmung und match nur Übereinstimmungen am Anfang der Zeichenkette zurück. Als weniger triviales Beispiel betrachten wir einen Textblock und einen regulären Ausdruck, der die meisten E-Mail-Adressen identifizieren kann:

>>> addresses = """Veit <veit@cusy.io>
... Veit Schiele <veit.schiele@cusy.io>
... cusy GmbH <info@cusy.io>
... """
>>> pattern = r'[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'
>>> regex = re.compile(pattern, flags=re.IGNORECASE)
>>> regex.findall(addresses)
['veit@cusy.io', 'veit.schiele@cusy.io', 'info@cusy.io']
>>> regex.search(addresses)
<re.Match object; span=(6, 18), match='veit@cusy.io'>
>>> print(regex.match(addresses))
None

regex.match gibt None zurück, da das Muster nur dann passt, wenn es am Anfang der Zeichenkette steht.

Angenommen, ihr möchtet E-Mail-Adressen finden und gleichzeitig jede Adresse in ihre drei Komponenten aufteilen:

  1. Personenname

  2. Domänenname

  3. Domänensuffix

Dazu setzt ihr zunächst runde Klammern () um die zu segmentierenden Teile des Musters:

>>> pattern = r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.([A-Z]{2,4})'
>>> regex = re.compile(pattern, flags=re.IGNORECASE)
>>> match = regex.match('veit@cusy.io')
>>> match.groups()
('veit', 'cusy', 'io')

re.Match.groups() gibt ein Tupel zurück, das alle Untergruppen der Übereinstimmung enthält.

re.Pattern.findall() gibt eine Liste von Tupeln zurück, wenn das Muster Gruppen enthält:

>>> regex.findall(addresses)
[('veit', 'cusy', 'io'), ('veit.schiele', 'cusy', 'io'), ('info', 'cusy', 'io')]

Auch in re.Pattern.sub() können Gruppen verwendet werden wobei \1 für die erste übereinstimmende Gruppe steht, \2 für die zweite usw.:

>>> regex.findall(addresses)
[('veit', 'cusy', 'io'), ('veit.schiele', 'cusy', 'io'), ('info', 'cusy', 'io')]
>>> print(regex.sub(r'Username: \1, Domain: \2, Suffix: \3', addresses))
Veit <Username: veit, Domain: cusy, Suffix: io>
Veit Schiele <Username: veit.schiele, Domain: cusy, Suffix: io>
cusy GmbH <Username: info, Domain: cusy, Suffix: io>

Die folgende Tabelle enthält einen kurzen Überblick über Methoden für reguläre Ausdrücke:

Methode

Beschreibung

re.findall()

gibt alle sich nicht überschneidenden übereinstimmenden Muster in einer Zeichenkette als Liste zurück.

re.finditer()

wie findall, gibt aber einen Iterator zurück.

re.match()

entspricht dem Muster am Anfang der Zeichenkette und segmentiert optional die Musterkomponenten in Gruppen; wenn das Muster übereinstimmt, wird ein match-Objekt zurückgegeben, andernfalls keines.

re.search()

durchsucht die Zeichenkette nach Übereinstimmungen mit dem Muster; gibt in diesem Fall ein match-Objekt zurück; im Gegensatz zu match kann die Übereinstimmung an einer beliebigen Stelle der Zeichenkette und nicht nur am Anfang stehen.

re.split()

zerlegt die Zeichenkette bei jedem Auftreten des Musters in Teile.

re.sub(), re.subn()

ersetzt alle (sub) oder die ersten n Vorkommen (subn) des Musters in der Zeichenkette durch einen Ersetzungsausdruck; verwendet die Symbole \1, \2, …, um auf die Elemente der Übereinstimmungsgruppe zu verweisen.

print()

Die Funktion print() gibt Zeichenketten aus wobei andere Python-Datentypen leicht in Strings umgewandelt und formatiert werden können, z.B.:

>>> import math
>>> pi = math.pi
>>> d = 28
>>> u = pi * d
>>> print("Pi ist", pi, "und der Umfang bei einem Durchmesser von", d, "Zoll ist", u, "Zoll.")
Pi ist 3.141592653589793 und der Umfang bei einem Durchmesser von 28 Zoll ist 87.96459430051421 Zoll.
>>> print(f"Der Wert von Pi ist {pi:.3f}.")
Der Wert von Pi ist 3.142.

In {pi:.3f} wird die Format-Spezifikation f verwendet, um die Zahl Pi

Eingebaute Module für Zeichenketten

Die Python-Standardbibliothek enthält eine Reihe eingebauter Module, mit denen ihr Zeichenketten managen könnt:

Modul

Beschreibung

string

vergleicht mit Konstanten wie string.digits oder string.whitespace

re

sucht und ersetzt Text mit regulären Ausdrücken

struct

interpretiert Bytes als gepackte Binärdaten

difflib

hilft beim Berechnen von Deltas, beim Auffinden von Unterschieden zwischen Zeichenketten oder Sequenzen und beim Erstellen von Patches und Diff-Dateien

textwrap

umbricht und füllt Text, formatiert Text mit Zeilenumbrüchen oder Leerzeichen