Modul: B-EPI
Einführung in die Programmierung EPR
VE08 Objektorientierten Programmierung (OOP) in Python
Prof. Dr. Franziska Matthäus / Prof. Dr. Matthias Kaschube / Dr. Karsten Tolle Institut für Informatik
Fachbereich Informatik und Mathematik (12)
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 2
EPI - Organisatorisches
OOP und UML Aufteilung:
Wann Thema Quiz
GPR 08 Intro OOP und UML,
Anwendungsfalldiagramm Zustandsdiagramm
Ja (Anwendungsfalls und Zustandsidagramm)
EPR 08 Klassen in Python Ja (Begriffe und Codeanalyse) GPR 09 OO-Paradigmen
Klassendiagramm Objektdiagramm
Ja (Klassen und Objekt-Diagramme)
EPR 09 Klassendiagramm Objektdiagramm
Nein – im GPR 09 Quiz enthalten EPR 10 eventuell
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 3
EPI - Organisatorisches
Die Welt der
Datentypen in Python
bool int
complex str Floating Point
tupel list
dictionnary function
float Ganzzahl
Wahrheitswert
Komplexe Zahlen Zahlen
Zeichenketten
frozenset set Sequenzen
range
Container None
elementare
Kollektionen
aufrufbar
unmutable mutable
class
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 4
EPI - Organisatorisches
Übersicht
Klassen in Python
‣ Die class - Anweisung
‣ Klasseninstanzen (Zugriff auf Attribute und Methoden - Punktnotation)
‣ Referenzzählung und Zerstörung von Instanzen
‣ Vererbung
‣ Überladen und Überschreiben
‣ Datenkapselung
‣ Introspektion
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 5
EPI - Organisatorisches
Klassen -die class – Anweisung
Klassen werden in Python durch die class – Anweisung definiert.
class ClassName:
""" Docstring. """
<anweisung-1>
. . .
<anweisung-N>
‣ In den Anweisungen werden
‣ Attribute (das Objektgedächtnis) durch Zuweisungen und
‣ Methoden durch def definiert.
Konvention:
Klassennamen werden in UpperCaseCamelCasing notiert, z.B. TypeError!
Ausnahmen bilden einige buildin Klassen (object, int,
…) (in C umgesetzt).
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 6
EPI - Organisatorisches
Ein Beispiel:
class Account:
"""A simple class for a bank account."""
account_type = "Basic"
def __init__(self, number, balance):
"""Initialize a new account."""
self.number = number self.balance = balance def deposit(self, amount):
"""Add to balance."""
self.balance += amount def withdraw(self, amount):
"""Subtract from balance."""
self.balance -= amount def inquiry(self):
"""Return current balance."""
return self.balance
Klassenattribut (Klassenvariable): account_type
Attribute (Instanzvariablen): number, balance
Funktionen werden im Kontext von Klassen Methoden genannt!
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 7
EPI - Organisatorisches
‣ Klassen definieren eine Menge von Variablen ( Attribute)
‣ zu unterscheiden sind:
‣ Instanzattribute:
Existieren für jedes Objekt (= Instanz) genau einmal.
Kennzeichen: Werden schreibend und lesend angesprochen durch
<self>.<attributname> innerhalb der Klasse
<Instanzname>.<attributname> außerhalb der Klasse
‣ Klassenattribute, statische Attribute, gelten für eine Klasse, haben für alle Instanzen dieser
Klasse denselben Wert. Klassenattribute existieren pro Klasse nur einmal; jedem Klassenattribut muss ein Initialwert zugewiesen werden. Zugriff durch <attributname>.
Als Konvention: Die Klassenattribute (statische Attribute) werden direkt unterhalb der class- Anweisung positioniert. (nach dem Docstring).
.
Attribute
account_type number
balance
Account
Unterstreichung kennzeichnet Klassenattribut.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 8
EPI - Organisatorisches
‣ Klassen definieren eine Menge von „Funktionen“, die auf den Attributen arbeiten (die nennen wir Methoden).
‣ Es gibt in Python drei Arten von Methoden:
‣ Instanzmethoden (sind an eine Instanz gebunden) und haben als ersten Parameter: self
‣ Instanzmethoden greifen auf die Instanzattribute zu.
‣ Kommen am häufigsten vor und sind die Default-Methoden.
‣ Statische Methoden
‣ Klassenmethoden
dieses sind Advanced Topics, die vergleichsweise selten genutzt
werden und andere Sprachkonstrukte wie Decorators benötigen.
Wir stellen diese Themen erst einmal zurück.
Methoden (1)
entspricht this in Java
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 9
EPI - Organisatorisches
Methoden (2)
‣ Instanzmethoden "normale" Methoden werden innerhalb einer class-Anweisung mit
definiert.
‣ Instanzmethoden sind an eine Instanz gebunden und werden von außerhalb aufgerufen mit
‣ von innerhalb der Instanz oder der Klasse mit:
Der Rumpf einer jeden Klasse enthält eine Folge von <statements>, die ausgeführt werden, wenn die Klasse definiert wird.
def method_name(self, <parameter>):
"""DocString."""
<statements>
<instance_name>.method_name(self, <parameter>)
method_name(self, <parameter>)
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 10
EPI - Organisatorisches
Instanzieren von Klassen (Konstruktor)
‣ Heißt: mithilfe der Schablonen (=Klassen) konkrete Instanzen (Exemplare, Objekte) erzeugen.
‣ Die Klassen-Instanziierung benutzt die Funktionsnotation:
„Man tut so“, als ob das Klassenobjekt eine parameterlose Funktion wäre, die eine neue Instanz der Klasse zurückgibt.
‣ Also zum Beispiel:
x = MyClass() #MyClass ist das Klassenobjekt.
Dies erzeugt eine neue Instanz der Klasse MyClass und weist dieses Objekt der lokalen Variable x zu.
# Account(number, balance) a = Account(1, 2)
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 11
EPI - Organisatorisches
Ein Beispiel:
class Account:
"""A simple class for a bank account."""
account_type = "Basic"
def __init__(self, number, balance):
"""Initialize a new account."""
self.number = number self.balance = balance def deposit(self, amount):
"""Add to balance."""
self.balance += amount def withdraw(self, amount):
"""Subtract from balance."""
self.balance -= amount def inquiry(self):
"""Return current balance."""
return self.balance
account_type number
balance
Account
__init__(number, balance) deposit(amount)
withdraw(amount) inquiry()
Klassendiagramm nach UML 2
Um account_type erweitert. Unterstreichung kennzeichnet Klassenattribut.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 12
EPI - Organisatorisches
Ein Beispiel:
class Account:
"""A simple class for a bank account."""
account_type = "Basic"
def __init__(self, number, balance):
"""Initialize a new account."""
self.number = number self.balance = balance def deposit(self, amount):
"""Add to balance."""
self.balance += amount def withdraw(self, amount):
"""Subtract from balance."""
self.balance -= amount def inquiry(self):
"""Return current balance."""
return self.balance
Dokumentations-String: String- Konstante direkt nach class Name:
Dieser String wird im Attribut _ _doc_ _ des Objekts gespeichert.
Auch bei Methoden anwenden!
Wird z.B. von help (ClassName)- Funktion ausgewertet.
Klassenvariablenwie account_type sind solche, die allen Instanzen einer Klasse identisch (in Typ und Wert) zur
Verfügung stehen, d.h. sie gehören nicht einzelnen Instanzen.
self.number und self.balance sind Instanzvariablen. Gut so, sonst hätte
jedes Konto denselben Kontostand.
„Funktionen“, die in einer Klasse definiert werden (also Methoden)
operieren immer auf einer Klasseninstanz, die als erstes
Argument übergeben wird.
Gemäß einer Konvention wird dieses erste Argument selfgenannt,
(obwohl jeder erlaubte Bezeichner möglich wäre).
Zugriff über:
Account.account_type
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 13
EPI - Organisatorisches
Ein Beispiel:
class Account:
"""A simple class for a bank account."""
account_type = "Basic"
def __init__(self, number, balance):
"""Initialize a new account."""
self.number = number self.balance = balance def deposit(self, amount):
"""Add to balance."""
self.balance += amount def withdraw(self, amount):
"""Subtract from balance."""
self.balance -= amount def inquiry(self):
"""Return current balance."""
return self.balance
Die Klasse bildet einen eigenen Namensraum. Auf die Attribute der Klasse Account kann
aus den Methoden heraus zugegriffen werden.
Details kommen später!
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 14
EPI - Organisatorisches
help(Account) (1)
Das zeigt die help-Funktion:
>>> help(Account)
Help on class Account in module __main__:
class Account(builtins.object)
| Account(number, balance)
|
| A simple class for a bank account.
|
| Methods defined here:
|
| __init__(self, number, balance)
| Initialize a new account.
|
| deposit(self, amount)
| Add to balance.
|
| inquiry(self)
| Return current balance.
builtins.object ist Superklasse von Account
Nach __init__() sind die methoden übrigens alphabetisch sortiert.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 15
EPI - Organisatorisches
help(Account) (2)
| withdraw(self, amount)
| Subtract from balance.
|
| ---
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
|
| ---
| Data and other attributes defined here:
|
| account_type = 'Basic'
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 16
EPI - Organisatorisches
Achtung:
Die class-Anweisung erzeugt keine Instanzen dieser Klasse.
Stattdessen definiert eine Klasse nur die Menge von Attributen und Methoden, über die alle Instanzen verfügen, sobald sie erzeugt werden, ist also eine Schablone.
Aber, mit der Definition werden die Klassen einmal ausgeführt (die Klassenattribute initialisiert und die Methoden bekannt gemacht, z. B. im obigen Beispiel:
account_type = "Basic")
Normale Funktionen, die innerhalb einer Klasse definiert werden (d.h. Methoden)
operieren immer auf einer Klasseninstanz, die als erstes Argument übergeben wird, laut Konvention self genannt.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 17
EPI - Organisatorisches
Zwischendurch zusammengefasst:
‣ Die class-Anweisung erzeugt ein Klassen-Objekt (keine Instanz dieser) und weißt diesem einen Namen zu:
‣ Zuweisungen auf oberster Ebene in der class-Anweisungen erzeugen Klassen-Attribute, die Zustand und Verhalten von Klassen exportieren.
‣ Methoden sind (ggf. verschachtelte) def mit einem speziellen ersten Parameter self, das die "Instanzvariable" aufnimmt.
‣ Zuweisungen an das Attribut self.x = obj innerhalb von Methoden erzeugen instanzspezifische Attribute (Instanzvariablen).
Nach Konvention Namen in UpperCamelCasing
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 18
EPI - Organisatorisches
Stichwort CamelCasing
PEP8:
‣ CapitalizedWords (or CapWords, or CamelCase -- so named because of the bumpy look of its letters. This is also sometimes known as StudlyCaps.
‣ mixedCase (differs from CapitalizedWords by initial lowercase character!) Konventionen anderer Programmiersprachen
Weder Gebrauch noch die Bezeichnungen sind einheitlich.
“For clarity, this article calls the two alternatives upper camel case (initial uppercase letter, also known as Pascal case) and lower camel case”.
en.wikipedia.org/wiki/Camel_case
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 19
EPI - Organisatorisches
Instanzen einer Klasse
‣ Werden erzeugt, indem ein Klassenobjekt (wie eine Funktion) aufgerufen wird.
‣ Dies erzeugt durch den Aufruf der Methode __new__() auf, die dann die Methode __init__() der Klasse aufruft, falls definiert.
Beispiel: zum Erzeugen von Konten:
‣ Diese Statements rufen dann (intern) die Methode new() und diese per Default die Methode init() auf.
rainers_account = Account(7654321, 100) annas_account = Account(1234567, 1000)
Instanzierung Achtung: Ohne self!
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 20
EPI - Organisatorisches
Beispiele:
RESTART: C:/Users/kroemker/AppData/Local/Programs/Python/Python37/Scripts/example_1.py
>>> rainers_account = Account(7654321, 100)
>>> annas_account = Account(1234567, 1000)
>>> rainers_account.deposit(100)
>>> annas_account.withdraw(150)
>>> print(rainers_account.account_type, rainers_account.number) Basic 7654321
>>> rainers_account.inquiry() 200
>>> annas_account.inquiry() 850
account_type number balance
Account
__init__() deposit() withdraw() inquiry() Rainers_account:Account
account_type = 'Basic' number = 7654321 balance = 200
Annas_account:Account account_type = 'Basic' number = 1234567 balance = 850
zu diesem Zeitpunkt
Objektdiagramm
Klassendiagramm
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 21
EPI - Organisatorisches
Referenzzählung und Zerstörung von Instanzen
‣ Alle Instanzen verfügen über einen Referenzzähler.
‣ Sobald dieser auf Null fällt, wird die Instanz zerstört (wie bei Variablen).
‣ Bevor die Instanz jedoch zerstört wird, sieht der Interpreter nach, ob für das Objekt eine Methode namens __del__() definiert ist, und ruft diese gegebenenfalls auf.
‣ Gelegentlich wird ein Programm die del-Anweisung verwenden, um andere Referenzen, offene Dateien, etc. zu löschen.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 22
EPI - Organisatorisches
Konstruktor (1)
Unter einem Konstruktor versteht man die Methode einer Klasse, die beim Aufruf des, aus der Klasse, erzeugten Objekts aufgerufen wird.
In Python ist dies die Methode
__init__(self, parameter1, parameter2, ...)
Es ist kein „echter“ Konstruktor im Java Sinn. Eher die Methode new().
Durch den Konstruktor werden den Attributen der Klasse Werte zugewiesen.
Was den Konstruktor von anderen Methoden unterscheidet ist, dass dieser nur beim Erzeugen des Objekts/der Instanz zum Einsatz kommt, also nach dem Erzeugen des Objektes mit __new__().
Erzeugt wird in Python eine neue Instanz indem man den Klassennamen wie eine Funktion aufruft (ohne den Parameter self).
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 23
EPI - Organisatorisches
Konstruktor (2)
‣ Häufig wird die __init__-Methode als Konstruktor bezeichnet. Wäre sie wirklich ein Konstruktor, würde sie wahrscheinlich __constr__ oder __constructor__ heißen.
‣ Sie heißt stattdessen __init__, weil mit dieser Methode ein Objekt /eine Instanz, welches vorher mit new() erzeugt ("konstruiert") worden ist, initialisiert wird.
‣ Die Methode __init__ wird also unmittelbar nach der "Konstruktion eines Objektes"
aufgerufen. Es wirkt also so, als würde das Objekt durch __init__ erzeugt.
Dies erklärt den häufig gemachten Fehler in der Bezeichnungsweise.
(Wird die __new__() Methode überschrieben, kann es sein, dass __init__ nicht aufgerufen wird!)
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 24
EPI - Organisatorisches
Zusammenfassung: Klassen und Instanzen in Python
Klassen sind der wesentliche Mechanismus, um
‣ Datenstrukturen und neue Datentypen zu definieren.
Klassen sind u.a. ein Mechanismus (irgendwo zwischen Unterprogrammen und Modulen) um ein Programm zu strukturieren.
Klassen haben einen eigenen Namensraum und die Möglichkeit instanz-spezifische Attribute (Daten) zu halten.
Klassen erlauben es, die charakteristische Art der OO-Analyse und des OO-Designs anzuwenden.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 25
EPI - Organisatorisches
Video live
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 26
EPI - Organisatorisches
Übersicht
Klassen in Python
‣ Die class - Anweisung
‣ Klasseninstanzen (Zugriff auf Attribute und Methoden - Punktnotation)
‣ Referenzzählung und Zerstörung von Instanzen
‣ Vererbung
‣ Überladen und Überschreiben
‣ Datenkapselung
‣ Introspektion
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 27
EPI - Organisatorisches
Vererbung in Python
‣ ist ein Mechanismus, um eine neue Klasse zu erzeugen, indem das Verhalten einer existierenden Klasse spezialisiert oder angepasst wird.
‣ Die ursprüngliche Klasse wird Basis- Ober- oder Superklasse genannt.
‣ Die neue Klasse wird abgeleitete oder Unterklasse genannt.
‣ Wenn eine Klasse mittels Vererbung erzeugt wird, »erbt« sie die Attribute und Methoden, die in ihren Basisklassen (ggf. über mehrere Generationen) definiert sind. Allerdings darf eine abgeleitete Klasse beliebige Attribute neu definieren oder neue Attribute selbst hinzufügen. (Man beachte, dass private Methoden nicht vererbt werden!)
‣ Vererbung wird in der class()-Anweisung mit einer durch Kommata getrennten Liste von Namen von Oberklassen angegeben.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 28
EPI - Organisatorisches
Beispiel
class A:
var_a = 42
def method1(self):
print("Klasse A : method1") def __method_privat(self):
print(„Nur in A vorhanden!") class B:
var_b = 37
def method1(self):
print("Klasse B : method1") def method2(self):
print("Klasse B : method2")
class C(A, B): # Erbt von A dann von B.
var_c = 3.3
def method3(self):
print("Klasse C : method3") class D: pass
class E(C, D): pass
Die Suche nach einem in einer Oberklasse definierten Attribut erfolgt mittels
Tiefensuche in der class()- Anweisung von links nach rechts, d.h. in der
Reihenfolge, in der die Oberklassen in der Klassen- definition angegeben wurden.
Die Oberklassen werden in der Reihenfolge C, A, B, D abgesucht (Tiefensuche). Für den Fall, dass mehrere Klassen das gleiche Symbol definieren, gilt, dass das zuerst gefundene Symbol genommen wird.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 29
EPI - Organisatorisches
Beispiel (2)
>>> c = C()
>>> c.method3() # Ruft C.method3(c) auf Klasse C : method3
>>> c.method1() # Ruft A.method1(c) auf Klasse A : method1
>>> c.var_b # Greift auf B.varB zu 37
>>>
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 30
EPI - Organisatorisches
Überschreiben (override) von Methoden
‣ Überschreiben (override) beschreibt eine Technik in der objektorientierten Programmierung, die es einer abgeleiteten Klasse erlaubt, eine eigene
Implementierung einer von der Basisklasse geerbten Methode zu definieren.
‣ Man schreibt in der abgeleiteten Klasse einfach eine Methode gleichen Namens!
‣ Dann ersetzt die überschreibende Methode der abgeleiteten Klasse die überschriebene Methode.
‣ Diese erbende Klasse kann neue Attribute hinzufügen und neue Methoden ersetzen oder hinzufügen. Es kann aber keine Methode oder Attribut
wegnenommen werden.
‣ Anmerkung: Es ist auch möglich in der überschreibenden Methode die Methode, die man überschreibt, aufzurufen (super().<Methodenname>).
Beispiel z.B. unter: https://www.python-kurs.eu/python3_vererbung.php#%C3%9Cberschreiben
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 31
EPI - Organisatorisches
Alles ist ein Objekt:
Die Klasse object
(davon sind alle Klassen abgeleitet)class object: The most base type.
(sagt der Interpreter und der muss es ja wissen! ;-) )
Dies sind die Methoden, die jedes Objekt hat und die man ggf. Anpassen (überschreiben) kann.
__new__() __init__() __str__()
__eq__(other)
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 32
EPI - Organisatorisches
Überladen (overloading) von Methoden
‣ Überladen kennt man beispielsweise in C++ und Java. Um es gleich vorweg zu sagen:
Es gibt kein Überladen von Methoden in Python. Es wird auch nicht benötigt.
‣ Überladen von Methoden wird in statisch getypten Sprachen wie Java und C++ benötigt, um die gleiche Funktion mit verschiedenen Typen oder verschiedener Anzahl von
Parametern zu definieren.
‣ … das geht in Python direkt und immer.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 33
EPI - Organisatorisches
Beispiel: "Überladen" (overloading) von Operatoren
‣ Klassen fangen eingebaute Operatoren ab und implementieren sie, indem sie Methoden mit speziellen Namen definieren, die mit zwei Unterstrichen beginnen und enden. Diese Namen werden von Oberklassen normal vererbt.
‣ Pro Operation wird genau eine Methode ausgeführt, sofern sie in der Suchhierarchie (siehe Namenskonventionen) gefunden wird, sonst tritt ein NameError auf.
‣ Python ruft also „automatisch“ die überladene Methode einer Klasse auf.
Wenn eine Klasse zum Beispiel die Methode namens __add__(self,other) definiert und a eine Instanz dieser Klasse ist, so ist a + other äquivalent zu a.add(other).
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 34
EPI - Organisatorisches
Zusammengefasst
‣ Klassen erben Attribute von allen in der Kopfzeile ihrer Klassendefinition angegebenen Klassen (Oberklassen). Die Angabe mehrerer Klassen bewirkt Mehrfachvererbung.
‣ Der Vererbungsmechanismus durchsucht zunächst die Instanz, dann deren Klasse, dann alle erreichbaren Oberklassen (von links nach rechts) und benutzt die erste gefundene Version eines Attribut- oder Methodennamens.
‣ Methoden können überschrieben werden, indem in der abgeleiteten Klasse eine Methode gleichen Namens definiert wird. Diese Methode kann beliebige Parameter haben!
‣ Den Mechanismus „überladen“ braucht man in Python nicht, weil Python dynamisch
„ge-typed“ ist.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 35
EPI - Organisatorisches
Video live
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 36
EPI - Organisatorisches
Übersicht
Klassen in Python
‣ Die class - Anweisung
‣ Klasseninstanzen (Zugriff auf Attribute und Methoden - Punktnotation)
‣ Referenzzählung und Zerstörung von Instanzen
‣ Vererbung
‣ Überladen und Überschreiben
‣ Datenkapselung
‣ Introspektion
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 37
EPI - Organisatorisches
Datenkapselung
‣ Allgemein gilt in Python, dass alle Attribute „öffentlich“ sind, d.h. alle Attribute einer Klasseninstanz sind ohne Einschränkungen überall sichtbar und zugänglich. Das
bedeutet auch, dass alles, was in einer Oberklasse definiert wurde, an Unterklassen vererbt wird und dort zugänglich ist.
‣ Dieses Verhalten ist in objektorientierten Anwendungen oft unerwünscht, weil es die interne Implementierung eines Objektes freilegt (Widerspruch zur Abstraktion) und zu Konflikten zwischen den Namensräumen von Objekten einer abgeleiteten und denen ihrer Oberklassen führen kann.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 38
EPI - Organisatorisches
Bisher …
Von: https://www.programiz.com/python-programming/property
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 39
EPI - Organisatorisches
Getter- und Setter-Methoden
Siehe auch:
https://www.programiz.com/python-programming/property
_temperature: Der Unterstrich zeigt an, dass der Programmierer ein direktes Verändern der Variable nicht will!
Durch die Get- und Set-Methoden können die Besonderheiten (hier die minimalste mögliche Temperatur) abgebildet werden.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 40
EPI - Organisatorisches
Namensraum bei Modulen
‣ Ein Namensraum ist eine Zuordnung von Namen zu Objekten.
‣ Beispiele für Namensräume sind: Die Menge der eingebauten Namen (z.B. die Funktionen wie abs()), die globalen Namen eines Moduls und die lokalen Namen eines Funktionsaufrufs.
‣ Das Wichtigste, das man über Namensräume wissen muss, ist, dass es absolut keinen Bezug von Namen in verschiedenen Namensräumen zueinander gibt.
‣ Zum Beispiel können zwei verschiedene Module eine Funktion namens maximize() definieren, ohne dass es zu einer Verwechslung kommt, wenn die Benutzer nicht
from module import *
benutzt haben, denn die Benutzer des Moduls müssen ja dessen Namen voranstellen, oder ihn eigens importiert haben.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 41
EPI - Organisatorisches
Wirkung einer Klassendefinition
‣ Wird eine Klassendefinition betreten, wird ein neuer Namensraum erzeugt und als lokaler Gültigkeitsbereich benutzt.
‣ Also: Zuweisungen erfolgen an lokale Variablen in diesem neuen Namensraum.
‣ Methodendefinitionen binden den Namen der neuen Methode in dem neuen Namensraum.
‣ Wird eine Klassendefinition normal verlassen (indem sie endet), wird ein Klassenobjekt erstellt. Der ursprüngliche lokale Gültigkeitsbereich (der vor dem Betreten der
Klassendefinition aktiv war) wird wiederhergestellt und das Klassenobjekt wird in ihm an den Namen, der im Kopf der Klassendefinition angegeben wurde, gebunden
(ClassName im vorherigen Beispiel).
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 42
EPI - Organisatorisches
Beispiel
Wenn die Klassendefinition also so aussah:
dann sind MyClass.i und MyClass.f gültige Attributreferenzen, die eine Ganzzahl beziehungsweise ein Funktionsobjekt zurückgeben.
Zuweisungen an Klassenattribute sind ebenfalls möglich, sodass man den Wert von MyClass.i durch Zuweisung verändern kann.
class MyClass:
"""A simple example class"""
i = 12345 def f(self):
return 'Hallo Welt'
x = MyClass.f y = MyClass() print(x(y))
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 43
EPI - Organisatorisches
Methoden als Instanzattribute
‣ Eine Methode ist eine Funktion, die zu einem Objekt gehört.
‣ (Anmerkung: In Python existiert der Begriff Methode nicht allein für Klasseninstanzen:
Andere Objekttypen können genauso Methoden haben. Zum Beispiel haben Listenobjekte Methoden namens append(), insert(), remove(), sort(), und so weiter.
‣ Jedoch benutzen wir im Folgenden den Begriff Methode ausschließlich im Sinne von Methoden von Klasseninstanzobjekten, sofern nichts anderes angegeben ist.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 44
EPI - Organisatorisches
Methodenattribute (1)
‣ Ob ein Attribut eine gültige Methode ist, hängt von der Klasse ab.
‣ Per Definition definieren alle Attribute, die ein Funktionsobjekt sind, ein entsprechendes Methodenobjekt für seine Instanz.
‣ Deshalb ist in unserem Beispiel x.f eine gültige Methodenreferenz, da MyClass.f eine Funktion ist.
‣ Aber x.i ist keine, da MyClass.i es nicht ist.
‣ x.f ist aber nicht dasselbe wie MyClass.f — es ist ein Methodenobjekt und kein Funktionsobjekt.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 45
EPI - Organisatorisches
Methodenattribute (2)
Üblicherweise wird eine Methode gemäß seiner Bindung aufgerufen:
Im MyClass Beispiel wird dies die Zeichenkette 'Hallo Welt' ausgeben.
Man kann eine Methode auch anders aufrufen: x.f ist ein Methodenobjekt und kann einer Variablen zugewiesen und später wieder aufgerufen werden. Zum Beispiel:
Das wird „bis zum Ende der Zeit“ Hallo Welt ausgeben.
x.f()
xf = x.f while True:
print(xf())
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 46
EPI - Organisatorisches
Was genau passiert wenn eine Methode aufgerufen wird?
‣ Oben wurde x.f() ohne Argument aufgerufen wurde, obwohl in der Funktionsdefinition für f() ein Argument festgelegt wurde.
‣ Was ist mit diesem Argument passiert? — Natürlich verursacht Python eine Ausnahme (einen Fehler), wenn eine Funktion, die ein Argument benötigt, ohne aufgerufen wird auch wenn das Argument eigentlich gar nicht genutzt wird ...
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 47
EPI - Organisatorisches
Besonderheit bei Methoden:
‣ das Objekt wird als erstes Argument der Funktion übergeben.
‣ In unserem Beispiel ist der Aufruf x.f() das genaue Äquivalent von MyClass.f(x).
‣ Im Allgemeinen ist der Aufruf einer Methode mit n Argumenten äquivalent zum Aufruf der entsprechenden Funktion mit einer Argumentliste, die durch das Einfügen des Objekts der Methode vor das erste Argument erzeugt wird.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 48
EPI - Organisatorisches
Genauer
‣ Wenn ein Instanzattribut referenziert wird, das kein Datenattribut ist, wird seine Klasse durchsucht.
‣ Bezeichnet der Name ein gültiges Klassenattribut, das eine Funktion ist, wird ein
Methodenobjekt erzeugt, indem (Zeiger zu) Instanzobjekt und Funktionsobjekt zu einem abstrakten Objekt verschmolzen werden: Dies ist das Methodenobjekt.
‣ Wird das Methodenobjekt mit einer Argumentliste aufgerufen, wird es wieder entpackt, eine neue Argumentliste aus dem Instanzobjekt und der ursprünglichen Argumentliste erzeugt und das Funktionsobjekt mit dieser neuen Argumentliste aufgerufen.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 49
EPI - Organisatorisches
(Fast) Private Daten in Klassen und Modulen
Für Klassen gelten dieselben Regeln wie für Module.
*) Aber dies ist keine echte Kapselung (privacy), da solche Namen voll qualifiziert noch genutzt werden können: <classname>._spam
Namen Bezeichnung Bedeutung
name public Attribute ohne führende Unterstriche sind sowohl innerhalb einer Klasse als auch von außen les- und schreibbar.
_name protected Man kann zwar auch von außen lesend und
schreibend zugreifen, aber der Entwickler macht damit klar, dass man diese Member nicht
benutzen sollte. *) __name private
(pseudo-privat)
Sind von außen nicht sichtbar und nicht benutzbar.
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 50
EPI - Organisatorisches
privat – mit Hintertür! - name mangling
class A:
def __init__(self):
self.x = 1 self.__y = 1
def getY(self):
returnself.__y
a = A() a.__y = 45 print(a.getY()) a._A__y = 45 print(a.getY()) pass
__y ist privat, der Wert von self.__y bleibt 1
hier wird dynamisch ein zusätzliches Attribut erzeugt. Der nächste print Befehl liefert daher „1“.
_A__y ist eine Hintertür und verändert self.__y 45 Der nächste printBefehl liefert daher „45“.
… sollte man ich machen!!!!
Sicht im PyCharm Debugger:
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 51
EPI - Organisatorisches
Dynamische Attribute
Dynamische Attribute (https://www.geeksforgeeks.org/dynamic-attributes-in-python/)
Output:
False – dynamisches Attribut!
True - Zugriff auf Klassenattribut (unschön, besser GFG.employee) Nikhil - dynamisches Attribut
Traceback (most recent call last): File
"/home/fbcfcf668619b24bb8ace68e3c400bc6.py", line 19, in print(e1.name) AttributeError: 'GFG' object has no attribute 'name'
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 52
EPI - Organisatorisches
(1) Attribute ohne _ am Anfang sind public.
(2) Alle Namen in einer Klasse, die mit einem doppelten Unterstrich beginnen, wie z.B. __Foo, werden „verstümmelt“, so dass __Foo die Form _ClassName__Foo annimmt: name
mangling.
Dies erlaubt es einer Klasse, private Attribute zu besitzen, da solche privaten Namen in einer abgeleiteten Klasse nicht mit den gleichen privaten Namen einer Oberklasse kollidieren können.
(3) Namen, die mit zwei Unterstrichen beginnen und mit zwei Unterstrichen enden (zum Beispiel __init__), haben eine besondere Bedeutung für den Interpreter: Klassen
fangen damit „eingebaute“ Operatoren ab und implementieren diese auf ihre Art (Überladen des Operators), indem sie Methoden mit zwei Unterstrichen beginnen und enden lassen, die sie von ihrer Oberklasse geerbt haben.
Zusammenfassung Konventionen (1)
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 53
EPI - Organisatorisches
(4) Klassennamen beginnen normalerweise mit einem großen Buchstaben, z.B.
MeineKlasse und benutzen CamelCasing.
(5) Der erste (am weitesten links stehende) Parameter der Methodendefinition innerhalb von Klassen wird self genannt.
(6) Qualifizierte Namen unterliegen den Regeln für Objekt-Namensräumen. Zuweisungen in bestimmten lexikalischen Geltungsbereichen (beziehen sich auf die Schachtelung im Quellcode eines Programmes) initialisieren Objekt-Namensräume (Module, Klassen).
Zusammenfassung Konventionen (2)
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 54
EPI - Organisatorisches
Zusammenfassung der Namenskonventionen (3)
Unqualifizierte Namen unterliegen auch lexikalischen Gültigkeitsregeln. Zuweisungen binden solche Namen an den lokalen Gültigkeitsbereich, es sei denn, sie sind als global deklariert.
Kontext Lokaler Bereich Globaler Bereich
Modul das Modul selbst wie kokal, das Modul
selbst
Funktion, Methode Funktionsaufruf umgebendes Modul
Klasse class-Anweisung umgebendes Modul
Skript,
interaktiver Modus
modul __main__ wie lokal
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 55
EPI - Organisatorisches
Introspektion
Introspektion (engl introspection, auch Reflexion (engl. reflection)) bedeutet, dass ein Programm Erkenntnisse über seine eigene Struktur gewinnen kann.
Python stellt einige eingebaute Funktionen bereit:
dir(), isinstance(), type(), id()
… es gibt auch ein eigenes Modul inspect
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 56
EPI - Organisatorisches
2x Video live
Prof. Dr. Franziska Matthäus Prof. Dr. Matthias Kaschube Dr. Karsten Tolle
Folie 57
EPI - Organisatorisches