Objektorientierte Programmierung mit Python Objekt und Klassen hat Kanten hat eine Farbe hat eine Kantenfarbe Rechteck zeichnen Rechteck einfärben Rechteck drehen
Modulare Programmierung Eine Aufgabe wird in viele kleine Aufgaben zerlegt. Jede kleine Aufgabe ist in sich abgeschlossen. Die Aufgabe kann von einem Entwickler-Team unabhängig von allen anderen programmiert werden. Jede kleine Aufgabe ist in einer Datei abgelegt. In dieser Datei werden die verschiedenen Aktionen in Funktionen abgelegt. Jede Funktion wiederum kann für sich allein getestet werden. Objektorientierte Programmierung, 09.09.10 Seite 2
Beispiel start.py def Main(): Anweisungen rechenoperationen.py def Addition(...): Anweisungen def Subtraktion(...): Anweisungen eingabebildschirm.py def Eingabe(): Anweisungen Objektorientierte Programmierung, 09.09.10 Seite 3
Objektorientierte Programmierung... abstrahiert Gegenstände der realen Wert, um sie in einem Programm abzubilden. beschreibt Objekte und verändert diese. versucht Daten und Funktionen eines Objekts in einer Struktur zu kapseln. Die Daten beschreiben das Objekt. Funktionen verändern die Attributwerte eines Objekts. Objektorientierte Programmierung, 09.09.10 Seite 4
Beispiel Füllfarbe Rechteck zeichnen Breite / Länge x- / y-position Kantenfarbe Rechteck Rechteck verschieben Rechteck füllen Attribute (Variablen) Aktionen (Funktionen) Objektorientierte Programmierung, 09.09.10 Seite 5
Prinzipien der objektorientierten Programmierung Abstraktion Objekte der realen Welt werden nachgebildet. Es werden nur die, für die Aufgabe des Projekts benötigten Elemente abgebildet. Datenkapselung: Für Außenstehende ist das Objekt eine Black Box. Variablen und die dazugehörigen Funktionen werden zusammengefasst. In dieser Black Box wird mit Hilfe von Variablen das Objekt beschrieben. Funktionen verändern die Variablen eines Objekts. Wie sie aber die Attribute verändern, ist dem Nutzer nicht bekannt. Objektorientierte Programmierung, 09.09.10 Seite 6
Objekte... beschreiben einen Gegenstand, Person etc. aus der realen Welt. sind Substantive in einem Text. haben Attribute (Eigenschaften), die das Aussehen des Objekts beschreiben. haben Methoden, die die Attribute verändern. Methoden spiegeln das Verhalten eines Objekts wieder. Objektorientierte Programmierung, 09.09.10 Seite 7
Beispiel Ein Würfel wird beschrieben: Der Würfel ist rot. Der Würfel hat eine Kantenlänge von 5 cm. Der Würfel kann gedreht werden. Der Würfel kann neu eingefärbt werden. Objektorientierte Programmierung, 09.09.10 Seite 8
und in Python Everything is a object. In Python ist jedes Element ein Objekt. Objekte in Python... können Variablen (Attribute) und Funktionen (Methoden) haben, müssen aber nicht. sind an einen bestimmten Datentyp gebunden. können an Funktionen übergeben werden. werden mit Hilfe von Klassen beschrieben. werden mit speziellen Methoden erzeugt und initialisiert. Objektorientierte Programmierung, 09.09.10 Seite 9
Beispiel: Funktion definieren und aufrufen «def Addition(zahlL, zahlr): return (zahll + zahlr)» summe = Addition(3, 5) print("addition(3, 5): ", summe) Objektorientierte Programmierung, 09.09.10 Seite 10
Beispiel: Funktion als Rückgabewert nutzen «def Addition(zahlL, zahlr): return (zahll + zahlr) def FunctionXYZ(arg01, arg02): return Addition(arg01, arg02)» summe = FunctionXYZ(3, 5) print("functionxyz(3, 5): ", summe) Objektorientierte Programmierung, 09.09.10 Seite 11
Beispiel: Funktion als Parameter nutzen «def Addition(zahlL, zahlr): return (zahll + zahlr) def FuncAsArgument(myFunction, arg01, arg02): return (myfunction(arg01, arg02))» summe = FuncAsArgument(Addition, 3, 5) print("funcasargument(addition, 3, 5) : ", summe) Objektorientierte Programmierung, 09.09.10 Seite 12
Beispiel: Alias für eine Funktion «def Addition(zahlL, zahlr): return (zahll + zahlr)» myaddition = Addition summe = myaddition(3,5) print("myaddition(3,5) : ", summe) Objektorientierte Programmierung, 09.09.10 Seite 13
Klassen... sind Baupläne, um bestimmte Objekt zu beschreiben. abstrahieren das Aussehen und Verhalten eines bestimmten Objekttyps. bieten eine Schablone, um Objekte abstrakt zu beschreiben. definieren Eigenschaften (Attribute) und Methoden, die alle Objekte eines bestimmten Typs besitzen. sind formale Beschreibungen für Objekte in einer bestimmten Programmiersprache. sind das Rezept, um ein bestimmtes Gericht herzustellen. Objektorientierte Programmierung, 09.09.10 Seite 14
Beispiel Welche Eigenschaften hat jeder Würfel? Farbe. Kantenlänge Welche Methoden hat jeder Würfel? Drehen. Einfärben. Zeichnen. Objektorientierte Programmierung, 09.09.10 Seite 15
Beschreibung mit Hilfe von UML Unified Modelling Language zur Darstellung von Klassen etc. Der Name der Klasse steht am oberen Rand. Dem Namen folgen die Attribute der Klasse und darunter die Methoden. In UML werden private Methoden und Attribute mit einem Minuszeichen und öffentliche Attribute und Methoden mit einem Pluszeichen gekennzeichnet. Wuerfel - farbe : string - kante: double +get_farbe() : string +get_laenge() : float +set_farbe() : string +set_laenge(): float +drehen_wuerfel() : void Objektorientierte Programmierung, 09.09.10 Seite 16
und in Python «class Rechteck(object): anzahl = 0 farbekante = "Black" farbefuellung = "White" def init (self, parabreite = 10, parahoehe = 10): self.hoehe = parahoehe self.breite = parabreite» def setpos(self, xpos, ypos): self.xpos = xpos self.ypos = ypos Objektorientierte Programmierung, 09.09.10 Seite 17
Klassenkopf «class Rechteck(object):» Jede Klasse beginnt mit dem Schlüsselwort «class». Dem Schlüsselwort folgt der Name der Klasse. Der Name ist frei wählbar. In den runden Klammern wird die Basisklasse «object» an die Klasse übergeben. Die Deklaration endet mit einem Doppelpunkt. Objektorientierte Programmierung, 09.09.10 Seite 18
Regeln für Klassennamen Es können die Buchstaben a...z, A...Z, die Zahlen 0...9 sowie der Unterstrich genutzt werden. Klassennamen beginnen mit einem Großbuchstaben. Häufig haben Klassennamen das Präfix C, um sie von anderen Elementen in Python zu unterscheiden. Unterscheidung zwischen Groß- und Kleinschreibung. Die Bezeichnungen c_rechteck und C_Rechteck bezeichnen unterschiedliche Klassen. Objektorientierte Programmierung, 09.09.10 Seite 19
Weitere Hinweise Nutzen Sie aussagekräftige Namen. Der Oberbegriff aus der realen Welt sollte auch für die dazugehörige Klasse in Python genutzt werden. Jedes Teilwort eines Klassennamen beginnt mit mit einem Großbuchstaben. Es sollte nur ein Sprachraum genutzt. In einer Datei werden nur englischsprachige oder nur deutschsprachige Bezeichnungen genutzt. Englischsprachige Begriffe sollten aber nicht mit aller Macht übersetzt werden, wenn sie allgemein verständlich sind. Schlüsselwörter der Programmiersprache Python dürfen nicht genutzt werden. Objektorientierte Programmierung, 09.09.10 Seite 20
in einer Projektbeschreibung Klassen entsprechen Substantiven in einer Projektbeschreibung. Das Konto wird für den Inhaber xyz von der Bank a eröffnet. Das Auto HI hat den Besitzer xyz. Mitarbeiter Müller arbeitet an dem Projekt Ausschreibung. Die Bestellung wird über einen Laserdrucker xyz ausgedruckt. Außendienstmitarbeiter Meier betreut Kunden im Bezirk Unterweser. Redundante oder für die Aufgabenstellung unnötige Klassen werden nicht implementiert. Objektorientierte Programmierung, 09.09.10 Seite 21
Basisklasse als Argument «class Rechteck(object):». In den runden Klammern wird der benutzerdefinierten Klasse eine Basisklasse übergeben. Die Basisklasse ist die Eltern-Klasse der benutzerdefinierten Klasse. ist die übergeordnete Klasse. beschreibt die Klasse allgemein. Als Basisklasse wird standardmäßig die vordefinierte Klasse «object» genutzt. Die runden Klammern können leer sein. Objektorientierte Programmierung, 09.09.10 Seite 22
Grafische Darstellung object list MyList dic classrechteck Objektorientierte Programmierung, 09.09.10 Seite 23
Klassenrumpf... folgt nach dem Doppelpunkt des Klassenkopfes. kann nur aus der leeren Anweisungen «class» bestehen. definiert Attribute, die von allen Objekten einer Klasse gemeinsam genutzt werden. definiert Methoden, um die Attribute, die jedes Objekt hat, zu verändern. definiert eine Initialisierungsmethode für Objekte einer bestimmten Klasse. Objektorientierte Programmierung, 09.09.10 Seite 24
Eine Instanz... ist eine Variable vom Datentyp Klasse. verweist auf ein bestimmtes Objekt einer bestimmten Kategorie. ist ein Synonym für ein Objekt. Das Objekt ist vom Typ der angegebenen Klasse. ist das mit Hilfe eines Rezept erstellte, fertige Gericht. kann beliebig oft von einer Klasse erzeugt werden. Objektorientierte Programmierung, 09.09.10 Seite 25
erzeugen RechteckBlau = classrechteck.rechteck() RechteckGruen = classrechteck.rechteck(20,30) In diesem Beispiel wird die Instanz «RechteckBlau» erzeugt. Die Instanz verweist auf ein Objekt von der Klasse «Rechteck». Die Klasse selber ist in dem Modul «classrechteck» implementiert. Klassen und deren Aufruf werden häufig in verschiedenen Dateien gespeichert. Objektorientierte Programmierung, 09.09.10 Seite 26
Ablauf Zuerst wird das Objekt mit der Methode «new» erzeugt. Anschließend werden mit Hilfe der Methode «init» mit Standardwerten initialisiert. Zum Schluss wird die Referenz auf das Objekt in der Instanzvariablen «RechteckBlau» gespeichert. Objektorientierte Programmierung, 09.09.10 Seite 27
Instanz zerstören «del RechteckBlau». Die Instanz wird aus dem Speicher entfernt. Nach der Löschung ist die Instanz undefiniert. Falls keine weitere Instanz von einer Klasse vorhanden ist, wird die Methode «del» aufgerufen. Objektorientierte Programmierung, 09.09.10 Seite 28
Attribute (Member)... beschreiben einen Gegenstand, Person, Funktion etc. Jedes Objekt einer Klasse hat die gleichen Attribute. Jedes Objekt einer Klasse unterscheidet sich aber in mindestens einem Attributwert von allen anderen Objekten. werden mit Hilfe von Variablen implementiert. Objektorientierte Programmierung, 09.09.10 Seite 29
in der Projektbeschreibung Attribute entsprechen meist der Beschreibungen eines Objekts. Das Auto ist rot und hat einen KM-Stand von 130.000. Die Milch ist pasteurisiert. Sobald ein Buch im Lager vorhanden ist, wird es an den Kunden ausgeliefert. Attribute sind Substantive, die einen Rückbezug auf ein anderes Substantiv besitzen. Die Menge des Artikels. Ausleihdatum des Buches. Anmeldung eines Autos. Objektorientierte Programmierung, 09.09.10 Seite 30
als Klassenvariable implementieren class Rechteck(object): anzahl = 0 farbekante = "Black" farbefuellung = "White" Objektorientierte Programmierung, 09.09.10 Seite 31
Klassenvariablen... werden innerhalb der Klasse, aber außerhalb einer Methode definiert. werden häufig zu Beginn des Klassenrumpfes aufgelistet. sind Attribute, die alle Objekte besitzen. können von jeden Objekt der Klasse verändert werden. sind globale Attribute eines Objekts. Objektorientierte Programmierung, 09.09.10 Seite 32
Mit Klassenvariablen arbeiten «Rechteck_Class.Rechteck.farbeFuellung = "Blue"» «Modul.Klasse.Attribut = Wert» Eine Klassenvariable kann nicht über die Instanz aufgerufen werden. Eine Klassenvariable kann nur mit Hilfe des Klassennamens verändert werden. Der Klassenname und das Attribut werden durch einen Punkt miteinander verbunden. Das Modul gibt Auskunft darüber, wo die Klasse definiert ist. Objektorientierte Programmierung, 09.09.10 Seite 33
Methoden (Memberfunction, Elementfunktion)... beschreiben das Verhalten eines Objekts. lesen oder verändern Attributwerte. beschreiben eine Schnittstelle nach außen. werden innerhalb der Klasse definiert. werden nur einmal für die Klasse im Speicher angelegt. ergeben sich aus den Attributen und deren Nutzung in einer Klasse. sind in Python immer öffentlich, können aber auch privat sein. entsprechen Funktionen aus der prozeduralen Programmierung. Objektorientierte Programmierung, 09.09.10 Seite 34
in der Projektbeschreibung Methoden sind meist Verben. Das Bankkonto wird eröffnet. Der Inhaber hebt eine bestimmte Summe von seinem Konto ab. Beschreibung einer Zustandsänderung / Änderung: Wenn die Ampel gelb ist, wird die Geschwindigkeit des Autos vermindert. Wenn die Helligkeit draußen einen bestimmten Prozentwert unterschreitet, wird die Straßenlaterne eingeschaltet. Eine Zugdurchfahrt wird gemeldet. Die Schranke wird geschlossen. Objektorientierte Programmierung, 09.09.10 Seite 35
in Python «class Rechteck(object): def setpos(self, xpos, ypos): self.xpos = xpos self.ypos = ypos» def getfarbefuellung(self): return self.farbefuellung) Objektorientierte Programmierung, 09.09.10 Seite 36
Methodenkopf Eine Methode beginnt mit dem Schlüsselwort «def». Dem Schlüsselwort folgt der Methodenname. Der Methodenname ist frei wählbar. Der Name kommt aber nur einmal in einer Klasse vor. Für den Methodennamen gelten die gleichen Regeln wie für Funktions- und Klassennamen. Dem Methodennamen folgt die Parameterliste. Als erster Parameter wird immer «self» oder eine andere Instanz angegeben. Der Methodenkopf endet mit dem Doppelpunkt. Objektorientierte Programmierung, 09.09.10 Seite 37
Methodenrumpf... ändern mit Hilfe von Anweisungen Attributwerte von Objekten oder Klassenvariablen. implementiert ein bestimmtes Verhalten einer Klasse. beschreibt eine Aktion der Klasse kann mit Hilfe von «return» einen Wert an den Aufrufer zurückgeben. Objektorientierte Programmierung, 09.09.10 Seite 38
Methoden aufrufen RechteckBlau.setPos(0, 10) RechteckBlau.getPos() print("füllungsfarbe: ", RechteckBlau.getFarbeFuellung()) Die Methode wird mit der Instanz immer durch ein Punkt verbunden. Falls die Methode nicht definiert ist, wird die Fehlermeldung AttributeError ausgegeben. Objektorientierte Programmierung, 09.09.10 Seite 39
Spezielle Methoden... sind in Python für «object» vordefiniert. beginnen und enden mit zwei Unterstrichen. haben einen definierten Namen. gibt es auch für Listen, Dictionaries etc. definieren Vergleiche oder mathematische Operationen. Objektorientierte Programmierung, 09.09.10 Seite 40
im Leben einer Instanz Instanz initialisieren Rechteck = classrechteck.rechteck() Methode new erzeugt ein Objekt Methode init initialisiert ein Objekt Mit dem Objekt arbeiten Rechteck.farbeFuellung = "Blue" Verweis auf das Objekt zerstören del Rechteck Methode del löscht ein Objekt Objektorientierte Programmierung, 09.09.10 Seite 41
Destruktor Mit Hilfe von «del RechteckBlau» wird automatisch der dazugehörige Destruktor «def del ()» aufgerufen. Als Parameter wird der Methode das zu zerstörende Objekt übergeben. Die Methode wird implementiert, wenn zum Beispiel... Netzwerkverbindungen getrennt werden müssen. Dateien geschlossen werden müssen. bestimmte Fehler abgefangen werden. Objektorientierte Programmierung, 09.09.10 Seite 42
in Python «class Rechteck(object):» def del (self): pass Objektorientierte Programmierung, 09.09.10 Seite 43
self als Parameter... ist ein Platzhalter für den Aufrufer der Methode. beantwortet die Frage Wer hat die Methode aufgerufen?. ist meist das erste Argument einer Methode. beschreibt die Instanz, die die Methode aufgerufen hat. Objektorientierte Programmierung, 09.09.10 Seite 44
Konstruktor initialisiert mit Hilfe der Methode «init» die Attributwerte eines Objekts. definiert einen Anfangszustand für ein Objekt. wird automatisch bei der Erzeugung einer Instanz aufgerufen. muss nicht implementiert werden. Objektorientierte Programmierung, 09.09.10 Seite 45
Merkmale eines Konstruktors Ein Konstruktor ist exakt einmal in einer Klasse implementiert. Die Initialisierungsroutine ist einmalig für eine Klasse. Dem Konstruktor können Parameter für die Initialisierung übergeben werden. Ein Konstruktor gibt nie einen Wert an den Aufrufer zurück. Objektorientierte Programmierung, 09.09.10 Seite 46
Python «class Rechteck(object):» def init (self, parabreite, parahoehe): self.xpos = 0 self.ypos = 0 self.hoehe = parahoehe self.breite = parabreite Objektorientierte Programmierung, 09.09.10 Seite 47
Aufbau der Parameterliste «self» ist der erste Parameter in der Liste. Welches Objekt wird initialisiert? Alle Parameter, die gesetzt werden müssen, folgen anschließend. Für diese Parameter muss ein Wert an die Initialisierungsroutine übergeben werden. Zum Schluss folgen optionale Parameter. Diese Parameter können bei der Initialisierung einer Instanz als Parameter übergeben werden, müssen aber nicht. Jeder dieser Parameter hat eine Vorgabe, die genutzt wird, wenn kein Parameter übergeben wird. Objektorientierte Programmierung, 09.09.10 Seite 48
Optionale Parameter nutzen «class Rechteck(object):» def init (self, parabreite = 10, parahoehe = 10): self.xpos = 0 self.ypos = 0 self.hoehe = parahoehe self.breite = parabreite Objektorientierte Programmierung, 09.09.10 Seite 49
Objektvariablen... beschreiben ein Objekt werden im Konstruktor einer Klasse initialisiert. werden in Abhängigkeit der Instanz gesetzt. haben für jedes Objekt einen anderen Wert. können mit Hilfe von Methoden verändert werden. können in einem Konstruktor definiert werden, müssen aber nicht. können in einer Methode definiert werden. Diese Variablen werden automatisch für das Objekt angelegt. Eine Hinweis für den Nutzer wird nicht herausgegeben. Das Programm wird dadurch schwer lesbar. Objektorientierte Programmierung, 09.09.10 Seite 50
im Konstruktor implementieren «class Rechteck(object):» def init (self, parabreite = 10, parahoehe = 10): self.xpos = 0 self.ypos = 0 self.hoehe = parahoehe self.breite = parabreite Objektorientierte Programmierung, 09.09.10 Seite 51
Klassen-Variablen im Konstruktor «class Rechteck(object): ANZAHL = 0 FARBE_KANTE = "Black" FARBE_FUELLUNG = "White"» def init (self, parabreite = 10, parahoehe = 10): self. xpos = 0 self. ypos = 0 self.hoehe = parahoehe self.breite = parabreite self.anzahl = self.anzahl + 1 Objektorientierte Programmierung, 09.09.10 Seite 52
Die Anweisung... «self.anzahl = self.anzahl + 1» legt für ein Objekt die Variable «ANZAHL» an. Zu dem undefinierten Wert der Objektvariablen wird der Wert eins addiert. Es findet kein Zugriff auf die Klassenvariable statt. Klassenvariable und Objektvariable besitzen aber den gleichen Namen. Objektorientierte Programmierung, 09.09.10 Seite 53
Klassen-Variablen im Konstruktor «class Rechteck(object): ANZAHL = 0 FARBE_KANTE = "Black" FARBE_FUELLUNG = "White"» def init (self, parabreite = 10, parahoehe = 10): self. xpos = 0 self. ypos = 0 self.hoehe = parahoehe self.breite = parabreite self. class.anzahl = self. class.anzahl + 1 Objektorientierte Programmierung, 09.09.10 Seite 54
Die Anweisung... «self. class.anzahl = self. class.anzahl + 1» greift auf die Klassenvariable «ANZAHL» zu. Zu dem Wert der Klassenvariable wird der Wert eins addiert. Das spezielle Attribut «class» definiert, die zu einer Instanz gehörenden Klasse. Objektorientierte Programmierung, 09.09.10 Seite 55
Der Begriff Sichtbarkeit... beschreibt den Zugriff auf Klassen- oder Objektattributen. von Variablen in Python wird nur mit Hilfe von Konventionen geregelt. Diese Konventionen sollten eingehalten werden, müssen aber nicht. Objektorientierte Programmierung, 09.09.10 Seite 56
Öffentlich, sichtbare Attribute... Beispiele: «Rechteck_class.Rechteck.FARBE_FUELLUNG = "Blue"» «RechteckBlau.xPos = 200» werden wie Variablen benannt. können von außen gelesen und verändert werden. als Klassenvariable: klasse.variable. als Objektvariable: objekt.variable. Klassenvariablen sind standardmäßig öffentlich. Objektorientierte Programmierung, 09.09.10 Seite 57
Private Attribute... Beispiele: «FARBE_KANTE = "Black"» «self. xpos = 0» beginnen mit zwei Unterstrichen. können laut Konvention nur innerhalb der Klasse gelesen und geschrieben werden. Ein Zugriff von außen auf diese Attribute ist nicht möglich. werden mit Hilfe von get-methoden gelesen. werden mit Hilfe von set-methoden verändert. Objektorientierte Programmierung, 09.09.10 Seite 58
Schwache private Attribute... Beispiele: «_FARBE_KANTE = "Black"» «self._xpos = 0» beginnen mit einem Unterstrich. können laut Konvention nur innerhalb der Klasse gelesen und geschrieben werden. Ein Zugriff von außen auf diese Attribute ist nicht möglich. werden mit Hilfe von get-methoden gelesen. werden mit Hilfe von set-methoden verändert. werden nicht durch die Anweisung «from import *» in eine Datei importiert. Objektorientierte Programmierung, 09.09.10 Seite 59
Get- und Set-Methoden für eine Klasse «class Rechteck(object): def init (self, parabreite = 10, parahoehe = 10): self. xpos = 0 self. ypos = 0 self.hoehe = parahoehe self.breite = parabreite def getposy(self): return self. ypos» def setposy(self, pos): self. ypos = pos Objektorientierte Programmierung, 09.09.10 Seite 60
Properties... binden get- und set-methoden an einen Attributnamen. kapseln Attribute eines Objekts. werden mit Hilfe der Funktion «property» erstellt. Objektorientierte Programmierung, 09.09.10 Seite 61
in Python «class Rechteck(object): def getposy(self): return self. ypos def setposy(self, pos): self. ypos = pos» ypos = property(getposy, setposy) Objektorientierte Programmierung, 09.09.10 Seite 62
Funktion property «property(get, set, del, docstring)» Alle Funktionen, die als Parameter übergeben werden, müssen definiert sein. Falls get-methoden als Parameter übergeben werden, kann das gekapselte Attribut gelesen werden. Falls set-methoden als Parameter übergeben werden, kann das gekapselte Attribut verändert werden. wird am Ende des Klassenrumpfes aufgerufen. Objektorientierte Programmierung, 09.09.10 Seite 63
aufrufen «print( RechteckBlau.yPos )». Der Name der Property wird mit dem Instanznamen durch den Punkt verbunden. Der Aufruf einer Property und eines Attributs ist gleich.. Objektorientierte Programmierung, 09.09.10 Seite 64
Lesender oder schreibender Zugriff Lesender Zugriff: «print( RechteckBlau.yPos )». Es wird automatisch die entsprechende get-methode aufgerufen. Schreibender Zugriff: «RechteckBlau.yPos = 100». Es wird automatisch die entsprechende set-methode aufgerufen. Falls keine set-methode implementiert ist, wird der Fehler AttributeError ausgegeben. Objektorientierte Programmierung, 09.09.10 Seite 65