Montag, 4. November 2013
Python Objekte, Wiederholung Aufrufstack (POS1: 2BHIF)
Objekte
In Python sind alle Elemente Objekte. Folgendes Beispiel enthält ein paar solche Objekte:def fun(x): # auch ein Objekt! y = x * x return y f2 = fun # f1 ist eine Refernz auf fun lst = [1, 2, fun] # Liste mit 3 Objekten l2 = lst # l2 ist eine Refernz auf obige Liste erg = fun(2) print(erg) erg = f2(3) print(erg) print(f2 == fun) print(l2 == lst) print(lst)
Folgendes Bild zeigt den Speicher, wenn das Progarmm in der Zeile 3 angelangt ist, nach dem
f2(3)
(ist ja fun(3)
) in der Zeile 12 Aufgerufen wurde.
Sie können den Ablauf unter folgendem Link testen: objects.py
Sie sehen auf der rechten Seite die Objekte, welche Python angelegt hat. Der linke Bereich ("Frames") zeigt den Speicher, den Python für die (globalen) Variablen anlegt sowie den Speicher für die aufgerufene Funktion. Für jede Funktion wird so ein Bereich (Frame) angelegt und beim beenden wieder zerstört.
Pfeile stellen Referenzen dar. Zum Beispiel stellt der Pfeil von
lst
zum Listenobjekt [1, 2, fun]
dar. Auch l2
ist eine Referenz zu dieser Liste.
In dieser Liste gibt es eine weitere Referenz zur Funktion
fun
. Funktionsnamen sind also Referenzen zu "Funktions-Objekten" (die den Code der Funktion "enthalten").
Aufrufstack
Beim folgenden Beispiel können Sie sehen, wie Frames sich bei den Aufrufen der Funktionfact()
stapeln und dann in Folge wieder zerstört werden:
def fact(n): if n > 1: return n * fact(n - 1) else: return 1 f = fact(5) print(f)
Folgendes Bild zeigt die Frames, wenn das Programm die Zeile 5 erreicht (aber nicht ausgeführt) hat. Sie sehen einen Stapel von Frames. Ein Frame pro Aufruf. Diese Frames werden anschließend bei jedem
return
wieder zerstört. Man nennt diesen Stapel Aufrufstack:
Sie können den Ablauf unter folgendem Link testen: fact.py
Klassen
Bei Klassen handelt es sich um benutzerdefinierte Typen. D.h. es werden Typen angelegt, für die benutzerdefinierte Methoden (also objektgebundene Funktionen) definiert werden können:class Car: def __init__(self, cartype, kind, serNr): self.cartype = cartype # die Attribute type, self.kind = kind # kind und self.serNr = serNr # serNr sind in der Instanz def maxSpeed(self): if self.kind == "pickup": # Wenn Pickup, dann langsamer return 100.0 else: return 130.0 passat1 = Car("VW/Passat", "regular_car", 11142) jetta1 = Car("VW/Jetta", "small_car", 11143) ram1 = Car("Dodge/Ram", "pickup", 22242) fleet = [passat1, jetta1, ram1] # Fuhrpark for car in fleet: print(car.cartype, car.maxSpeed(), "km/h")
Mittels der Anweisung
class
wird ein neuer Typ definiert. Dieser heißt in diesem Fall ‘Car’. Wir sehen, dass es sich bei der class
Anweisung ebenfalls um eine Block - Anweisung handelt, da nach der Bezeichnung der Klasse (Car) der Doppelpunkt folgt und die danach folgenden Methoden eingerückt sind.
Die einzelnen Methoden werden wie Funktionen definiert. D.h. die Definition erfolgt durch das Schlüsselwort
def
. Als Unterschied gibt wird jedoch ein zusätzlicher Parameter an erster Stelle angeführt, der zur Ausführungszeit der Methode mit der Referenz des aktuellen Objektes vom Laufzeitsystem belegt wird.
Das folgende Bild zeigt, wie Python den Speicher für die Objekte und die Klasse angelegt hat.
Sie können das Programm hier ausführen car.py.
Die Ausgabe wäre wie folgt:
VW/Passat 130.0 km/h VW/Jetta 130.0 km/h Dodge/Ram 100.0 km/h
Durch Aufrufen der Klasse (durch Angabe des Klassennamens) und Übergabe der Initialisierungsparameter wird eine neue Instanz angelegt. Die übergebenen Parameter werden verwendet, um die spezielle Methdode
__init__
nach dem Anlegen der Instanz aufzurufen. D.h. zuerst wird das neue Objekt angelegt und danach wird diese spezielle Methode aufgerufen. Dazu wird auch dieser Methode die Referenz auf das gerade angelegte Objekt mitgegeben (als Parameter self
).
D.h. in der Methode
__init__
werden die Attribute cartype
, kind
und serNr
für das gerade erzeugte Objekt angelegt. D.h. ab diesem Zeitpunkt besitzt das Objekt diese Attribute. Die Methode maxSpeed
kann danach ebenfalls auf diese Attribute zugreifen.
Attribute gehören also zu einem Objekt und können in den Methoden abgefragt und verändert werden. Anders als in anderen Programmiersprachen ist es jedoch so, dass der Zugriff auf diese Attribute nicht nur ausschließlich in den Methoden erfolgen kann. Diese Attribute können prinzipiell auch von außerhalb gelesen und verändert werden, wie man in obigem Beispiel in der Zeile 21 (
print(...)
) sehen kann.
Abonnieren Posts [Atom]
Kommentar veröffentlichen