Suche in Zeichenketten

Wir können nun eine Funktion schreiben, die zählt, wie oft ein gegebenes Zeichen in einer Zeichenkette vorkommt:

def count_char(text, char):
  count = 0
  for index in range(0, len(text)):  # len(x) liefert die Länge des Textes x
    if text[index] == char:
      count = count + 1
  return count

Hierzu durchlaufen wir in einer Zählschleife alle Zeichen der Zeichenkette text und erhöhen den Zähler count, wenn wir das gesuchte Zeichen char finden. Die Zahlvariable index durchläuft die Indizes dabei mit 0 beginnend.

Hier sind einige Beispielaufrufe:

>>> count_char('Hallo Welt!','l')
3
>>> count_char('Hallo Welt!','!')
1
>>> count_char('Hallo Welt!','x')
0

In Python vermeidet man nach Möglichkeit Index-Variablen und die Iteration über einen Bereich. Stattdessen wird über die Elemente des zu iterierenden Objektes direkt iteriert:

def count_char(text, char):
  count = 0
  for c in text:
    if c == char:
      count = count + 1
  return count

Die Erzeugung eines Range-Objektes und die Verwendung von Indizes lässt sich meist zu Gunsten eines einfacheren, besser lesbaren Codes vermeiden.

Wenn wir nur daran interessiert sind, ob das Zeichen enthalten ist, aber nicht daran wie oft, können wir die Suche bei Erfolg vorzeitig zu beenden, indem wir eine return-Anweisung in dem Rumpf der Schleife einfügen:

def has_char(text, char):
  for index in range(0, len(text)): 
    if text[index] == char:
      return True
  return False 

Ohne Verwendung eines Index lässt sich die Funktion wie oben vereinfachen:

def has_char(text, char):
  for c in text:
    if c == char:
      return True
  return False

Im Fall, dass das Zeichen char im text gefunden wird, wird die Funktion mit Rückgabewert True sofort verlassen und die for-Schleife nicht vollständig durchlaufen. Wird das Zeichen nicht gefunden, läuft die for-Schleife vollständig und die Funktion endet mit der Rückgabe von False

Diese Funktion können wir wie folgt verwenden:

>>> has_char('Hallo Welt!', 'l') 
True 
>>> has_char('Hallo Welt!', '!') 
True 
>>> has_char('Hallo Welt!', 'x') 
False

Wir können auch nach Teilstrings beliebiger Länge suchen und müssen dazu die selektierte Länge an den gesuchten String anpassen. In diesem Beispiel könnne wir auf den Index nicht verzichten, da wir die Slice-Funktion [:] verwenden müssen:

def has_string(text, string):
  for index in range(0, len(text)-len(string)): 
    if text[index:(index + len(string))] == string:
      return True
    index = index + 1
  return False

Zur Illustration wieder einige Beispiele:

>>> has_string('Hallo Welt!', 'llo')
True
>>> has_string('Hallo Welt!', 'lol')
False
>>> has_string('Hallo Welt!', 'welt')
False

Es wird also Groß- und Kleinschreibung unterschieden.

Schließlich können wir dieses Programm noch so abwandeln, dass es den ersten Index zurück gibt, an dem der gesuchte String gefunden wurde (bzw. den Fehlerwert None, falls er nicht gefunden wird).1

def index_of(text, string):
  for index in range(0, len(text)-len(string)): 
    if text[index:(index + len(string))] == string:
      return index
  return None

Wieder ein paar Beispielaufrufe zur Illustration:

>>> index_of('Hallo Welt!', 'Hallo')
0
>>> index_of('Hallo Welt!', 'Welt')
6
>>> index_of('Hallo Welt!', 'welt')

Das Ergebnis None des letzten Aufrufs wird in der interaktiven Python-Umgebung nicht angezeigt.

Mit der vordefinierten Funktion open() können wir den Inhalt von Textdateien einlesen. Dabei erhalten wir ein File-Objekt, das wir mit read() in eine Zeichenkette umwandeln können. Dies ermöglicht es uns, auch in größeren Texten, zum Beispiel in unserem Programm, nach Zeichenketten zu suchen.

>>> source = open('strings.py').read()
>>> indexOf(source,"def has_string")
365

  1. Der Wert None wird in Python dort verwendet, wo kein sinnvoller Wert möglich ist. Viele Programiersprachen stellen ähnliche Werte bereit, die dort z.B. null oder nil heißen. ↩︎