Kapitel 13
Verarbeitung von Zeichenketten
398
Aufgabe 5
Entwickeln Sie für ein Online-Warenhaus einen Chat Bot, der wütende Kunden besänftigt,
die sich über lange Lieferzeiten und andere Dinge beschweren. Das Programm versucht
– durch eine Analyse des Textes – herauszufinden, worum es in der Beschwerde geht, und
findet eine angemessene Antwort.
Beispieldialog:
13.8 Lösungen
Lösung 1
Skript:
Melanie: Hallo, ich bin Melanie, der Beschwerde-Roboter des Magnum
Online-Warenhauses. Was kann ich für Sie tun?
Kunde: Ich will mit einem richtigen Menschen sprechen, nicht mit einer
Maschine!!
Melanie: Ich verstehe Ihr Problem, aber ich kann leider nichts dazu
sagen. Vielleicht kann ich Ihnen auf andere Weise weiterhelfen ...
Kunde: Vor vier Wochen habe ich ein Radio bestellt, aber es ist immer
noch nicht gekommen!
Melanie: Das ist ungewöhnlich. Wir bearbeiten alle Aufträge umgehend.
Aber manchmal gibt es Lieferschwierigkeiten.
Kunde: Na gut ... danke.
Melanie: Auf Wiedersehen. Wenn Sie noch eine Frage haben, melden Sie
sich einfach.
# staumelder.py
from random import *
muster1 = """Ein Stau von {laenge} km Länge
erwartet Sie auf der {autobahn} Richtung {richtung}
vor {abfahrt}.\n\n""" #1
muster2 = """Auf der {autobahn} Richtung {richtung}
vor {abfahrt} {laenge} km Stau.\n\n"""
muster = [muster1, muster2] #2
class StauBericht(object):
def __init__(self, stauliste, muster): #3
self.stauliste = stauliste
399
13.8
Lösungen
Erläuterung:
#1: Hier werden zwei globale Konstanten mit Textmustern für Stauberichte definiert. Diese
enthalten Strings mit Platzhaltern für die Daten eines Staus (Autobahn, Richtung usw.).
#2: Dies ist eine Liste mit Mustertexten, von denen zur Formulierung einer Staumeldung
einer ausgewählt werden kann.
#3: Das zweite Argument der Initialisierungsmethode enthält eine Liste von Tupeln mit
Staudaten, die dem Objektattribut
self.stauliste zugewiesen wird. Das dritte Argument
ist die Liste mit Textmustern für Staumeldungen.
#4: Hier wird eine Zufallszahl erzeugt, mit der man ein zufälliges Textmuster aus der Liste
self.muster auswählen kann.
#5: Ein zufällig ausgewählter Mustertext für die Staumeldung wird mithilfe der Methode
format() mit Daten verknüpft. Die Platzhalter im Mustertext werden durch Staudaten
ersetzt.
#6: Hier wird der gesamte Staubericht aus lauter einzelnen Staumeldungen zusammenge-
setzt.
self.muster = muster
def meldeStau(self, stau):
autobahn, richtung, abfahrt, laenge = stau
zufall = randint(0, len(self.muster) - 1) #4
meldung = self.muster[zufall].format(
autobahn=autobahn,
richtung=richtung,
abfahrt=abfahrt,
laenge=laenge) #5
return meldung
def __str__(self): #6
bericht = ''
for stau in self.stauliste:
bericht += self.meldeStau(stau)
return bericht
# Hauptprogramm
staus = [('A1','Köln', 'dem Westhofener Kreuz', 4),
('A40', 'Dortmund', 'der Abfahrt Bochum Zentrum', 6)]
print(StauBericht(staus, muster)) #7
Kapitel 13
Verarbeitung von Zeichenketten
400
#7: Ein anonymes Objekt der Klasse Staubericht wird instanziiert und mittels print()
ausgegeben. Dies funktioniert, weil in der Klasse Staubericht mit __str__() die Stan-
dardfunktion
str() überladen worden ist.
Lösung 2
Skript:
# pinnwand.py
# Modellierung einer intelligenten Pinnwand
class Pinnwand(object):
def __init__(self):
self.__zettel = []
def __ermittlePrioritaet(self, notiz): #1
return notiz.count('!')+ \
notiz.upper().count('WICHTIG') + \
notiz.upper().count('DRINGEND') + \
notiz.upper().count('EILT')
def hefteAn(self, notiz): #2
self.__zettel.append(
(self.__ermittlePrioritaet(notiz), notiz))
self.__zettel.sort() #3
self.__zettel.reverse()
def __str__(self):
beschreibung = 'Notizen\n' #4
for z in self.__zettel:
beschreibung += z[1]
beschreibung += '(Prioritaet: '+str(z[0])+')\n'
return beschreibung
def entferne(self):
notiz = self.__zettel[0][1]
del self.__zettel[0]
return notiz
class Benutzungsoberflaeche(object):
__menuetext = """
(N)eue Notiz anheften (A)lle Notizen auflisten
(W)ichtigste Notiz entfernen (E)nde
"""
401
13.8
Lösungen
Erläuterung:
Das Skript besteht aus zwei Klassendefinitionen und einem kleinen Hauptprogramm (
#5),
in dem Objekte der Klassen
Pinnwand und Benutzungsoberflaeche instanziiert werden.
Durch den Aufruf der Methode
menue.run() in der letzten Zeile wird die Benutzungsober-
fläche sozusagen »aktiviert« und der Dialog mit der Pinnwand beginnt.
#1: Es wird geprüft, wie häufig ein Ausrufungszeichen und die Strings wichtig, dringend
und eilt (unabhängig von Groß- und Kleinschreibung) in der Notiz vorkommen. Die
Summe dieser Vorkommen ergibt die Priorität der Notiz.
#2: An die Liste self,__zettel wird ein neues Tupel, bestehend aus der Priorität und dem
Text der Notiz, gehängt. Anschließend wird die Liste aufsteigend sortiert (
#3) und dann die
Reihenfolge umgekehrt. Die Liste ist also anschließend absteigend sortiert, so dass das
Tupel mit der höchsten Priorität vorne ist.
#4: Die Methode überlädt die Standardfunktion str() und liefert eine textuelle Beschrei-
bung aller Notizen einschließlich ihrer Priorität.
def __init__ (self, pinnwand):
self.__pw = pinnwand
def run(self):
wahl = '-'
print('Pinnwand')
while wahl not in 'Ee':
print(self.__menuetext)
wahl = input('Ihre Wahl: ')
if wahl in 'nN': self.__neu()
elif wahl in 'aA': print(self.__pw)
elif wahl in 'wW':
print(self.__pw.entferne())
print("Danke für die Verwendung der Pinnwand!")
def __neu(self):
notiz = input('Notiz: ')
while notiz:
self.__pw.hefteAn(notiz)
notiz = input('Notiz: ')
# Hauptprogramm #5
pinnwand = Pinnwand()
menue = Benutzungsoberflaeche(pinnwand)
menue.run()

Get Python 3 - Lernen und professionell anwenden now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.