[ Home ] [ Seitenende ]

 

 

 

Micropython, Teil 3

 

Im zweiten Teil dieses Tutorials sind wir beim Programm „micro_python-hallo_2-40.py stehengeblieben bei dem es darum ging, eine übergeordnete Instanz namens „Instanz_Klasse_1“ anzulegen und der untergeordneten Klasse „Klasse_1“ zuzuordnen. Den Vorgang nennt man deshalb auch „Instanziieren“ oder „Instanzierung“.

 

Was aber soll man sich unter einer Instanz vorstellen? Bezüglich der Judikation, d.h. des Rechtswesen und der Rechtsprechung hatten wir das ja schon besprochen. Nämlich wenn man gegen ein Urteil z.B. des örtlich ansässigen Amtsgerichtes Widerspruch einlegt, dann geht es mit dem Verfahren zur nächst höheren Instanz wie z.B. dem Landgericht.

 

Im Mittelalter und auch noch heutzutage gibt es den Volksspruch: „Gehe nicht zu deinem Fürst, wenn du nicht gerufen wirst!“ Damit ist gemeint, dass man nicht die nächst höhere Instanz, wie z.B. den Chef, wegen jeder Kleinigkeit oder Unzufriedenheit aufsuchen und diesen behelligen soll. Diesbezüglich gibt es noch eine weitere Volksweisheit: „Was der Chef nicht weiß, macht ihn nicht heiß!“ Das bedeutet, dass der Chef als nächst höhere Instanz nicht alles wissen muss, nicht über alles bis ins Detail informiert sein muss. Schließlich verfügt jeder Mitarbeiter im Betrieb um sein heimliches „Herrschaftswissen“, das er den anderen aus taktischen und strategischen Gründen vorenthält.

 

Kurz und gut, eine Instanz ist einfach etwas Höheres, was auch immer das konkret sein mag. Man könnte es also auch im einen oder anderen Fall als Wichtigtuerei abtun.

 

Bei der Programmierung jedenfalls steht eine Instanz über einer Klasse und eine Klasse über einer Funktion (siehe Programm „micro_python-hallo_3-1.py).

 

Und, wenn es eine Instanz zu einer Klasse gibt und die Klasse wiederum eine untergeordnete Funktion enthält, dann spricht man nicht mehr von einer Funktion, sondern von einer Methode (= „gewusst wie“, Anleitung, Rezeptur zwecks Erreichen eines Ziels oder, um ein bestimmtes, vorgegebenes Produkt nach Vorgabe zu produzieren). Demzufolge ist eine Methode programmiertechnisch stets das Zusammenspiel zwischen einer Klasse und einer untergeordneten Funktion.

 

Im Programm „micro_python-hallo_3-1.py gibt es nun zwei Instanzen, und zwar zu jeder Klasse eine:

 

·       Instanz „Instanz_Klasse_1“ zur „Klasse_1“ und

 

·       Instanz „Instanz_Klasse_2“ zur „Klasse_2“.

 

Mittels der beiden Instanzen können wir nun sowohl auf die Klasse „Klasse_1“ und deren untergeordneten Funktion „Funktion_1()“ als auch auf die Klasse „Klasse_2“ und deren untergeordneten Funktion „Funktion_2()“ zugreifen und dabei mittels des

 

·       Statements „Instanz_Klasse_2.EmpfangsVar = Instanz_Klasse_1.SendeVar

 

einen Datenaustausch von der Variablen „SendeVar“ zur Variablen „EmpfangsVar“ vornehmen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie wir bereits wissen, werden Klassen beim Programmstart automatisch im Hintergrund aufgerufen und ausgeführt, sodass diese vom Hauptprogramm aus nicht explizit aufgerufen werden müssen. So weit der Vorteil von Klassen. Aber wo Licht ist, ist auch Schatten, lassen sich Klassen nicht per se ein weiteres Mal aufrufen und ausführen! Es sei denn man programmiert um die Klassen herum eine entsprechende Funktion!

 

Funktionen haben nämlich den Vorteil, dass sie sich jederzeit z.B. vom Hauptprogramm aus beliebig oft aufrufen und ausführen lassen! Mit samt den darin befindlichen Klassen, die beim Funktionsaufruf ebenfalls mit ausgeführt werden (siehe Programm „micro_python-hallo_3-2.py):

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wenn man aber wie im obenstehenden Programm „micro_python-hallo_3-2.py“ um die beiden Klassen „Klasse_1“ und „Klasse_2“ eine entsprechende Funktion drum herum programmiert, dann kommt man auf herkömmliche Weise wider Erwarten nicht mehr so ohne Weiteres an die Variablen nebst Variableninhalte innerhalb einer Klasse. Es sei denn, man greift zu einem kleinen Trick und lässt sich die Variableninhalte mittels des „return“-Statements z.B. an das Hauptprogramm wieder zurückgeben (siehe grüne Kästen im obenstehenden Bild):

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Der entscheidende Nachteil der zuvor genannten Methode, Variableninhalte über das „return“-Statement nach außen zu transferieren, ist leider der, dass man dazu stets die entsprechende Methode selbst aufrufen muss. In der Programmierpraxis gibt es aber oft Situationen, wo genau das nicht erwünscht oder sogar unmöglich ist.

 

Wie man sieht, kommt das Programm „micro_python-hallo_3-3.py ganz ohne des „return“-Statements zwecks Transferierens von Dateninhalten aus, weil die ehemalige, äußere Funktion „tausche_Daten()“ durch die äußere Klasse „Container_Klasse“ ersetzt wurde:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Bei genauerem Studium des obenstehenden Quellkodes fällt auf, dass die lokale Variable „lokale_EmpfangsVar“ in der Methode „Funktion_2()“ in Wirklichkeit leer ist bzw. den Variableninhalt „…“ enthält, weil sich der Variableninhalt „Ich bin Text aus der Funktion 1!“ der Variablen „lokale_SendeVar“ „SendeVar“ „SendeVar = Klasse_1.SendeVar“ wider Erwarten nicht der Variablen „EmpfangsVar“ innerhalb der Klasse „Klasse_2“ zuweisen lässt!

 

Diesbezüglich stellt sich dann gleich die Frage, wie die Variable „EmpfangsVar“ trotzdem zum Variableninhalt „Ich bin Text aus der Funktion 1!“ kommt!

 

Ganz einfach: durch das

 

·       Statement „Instanz_Container.EmpfangsVar = Container_Klasse.SendeVar

 

(siehe grüner Kasten im Hauptprogramm):

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man im obenstehenden Programmkode sieht, wird die Klasse „Klasse_2“ überhaupt nicht mehr gebraucht, weil der Datentransfer von der Variablen „SendeVar“ zur Variablen „EmpfangsVar“ zwischen den Instanzen „Container_Klasse“ und „Instanz_Container“ erfolgt (siehe Programm „micro_python-hallo_3-4.py).

 

 

Von Instanzen zum Objekt orientierten Programmieren (OOP)

 

So, nun sind wir ohne es zunächst bemerkt zu haben, beim Programmieren von Objekten angekommen. Wie aber ist das möglich? Was ist überhaupt ein Objekt? Und wie wird aus einer Instanz ein Objekt? Erinnern wir uns:

 

Eine Funktion in Kombination mit einer darüber befindlichen Klasse nennt man Methode.

 

Und eine Klasse in Kombination mit einer darüber befindlichen Instanz in Form einer übergeordneten Klasse oder Funktion(!) wird zur Instanz.

 

Gibt man dieser übergeordneten Instanz einen sinnverwandten Namen wie z.B. „Objekt_Container“, dann wird aus der Instanz ein Objekt:

 

·       Statement „Objekt_Container = Container_Klasse()

 

Im Zusammenhang mit der Instanziierung der übergeordneten Klasse „Container_Klasse“ zum Objekt „Objekt_Container“ und dem Datenaustausch z.B. zwischen der Instanzvariablen „SendeVar“ und der Objektvariablen „EmpfangsVar“ ist es zwingend notwendig, die Instanz „Container_Klasse“ zuvor zum Objekt „Objekt_Container“ zu instanziieren:

 

·       Statement „Objekt_Container = Container_Klasse()

·       Statement „Objekt_Container.EmpangsVar = Container_Klasse.SendeVar

 

Durch die Instanziierung der Instanzvariablen „SendeVar“ zur Objektvariablen „EmpfangsVar“ wird also nicht automatisch zuvor noch das Objekt „Objekt_Container“ instanziiert (siehe Programm „micro_python-hallo_3-5.py).

 

Bei der Instanziierung der übergeordneten Klasse „Container_Klasse“ zum Objekt „Objekt_Container“ gilt es zu beachten, dass das Objekt „Objekt_Container“ alle Eigenschaften (= Attribute), d.h. untergeordnete Klassen, Funktionen, aber auch Variablen inkl. der Variableninhalte, von der Klasse „Container_Klasse“ erbt!

 

Bei der Instanziierung einer übergeordneten Klasse (oder Funktion) zum Objekt, erbt das Objekt alle Eigenschaften von der Klasse, ist also demzufolge ein 1:1 Abbild der Klasse, aber mit dem entscheidenden Vorteil, dass sich das Objekt jederzeit um weitere untergeordnete Funktionen, Klassen, Variablen usw. erweitern lässt, während die vererbende Klasse dabei selbst unverändert bleibt (siehe Programm „micro_python-hallo_3-6.py)! -

 

 

Zur besseren Veranschaulichung stelle man sich folgendes vor: Ein mehrköpfiges Programmierteam hat im Laufe von mehreren Jahren ein umfangreiches „Python“-Programm, das aus mehreren Modulen und zehntausenden von Programmzeilen Kode besteht, programmiert und erfolgreich abgeschlossen, d.h. auf den Kunden losgelassen. 

 

Nach fünf Jahren meldet sich der Kunde wieder und möchte sein diesbezügliches Programm um etliche Funktionen erweitert haben, sodass dieses entsprechend leistungsfähiger wird. Das Problem dabei ist aber, dass es die damaligen Programmierer aus dem Programmierteam nicht mehr gibt! Aber nicht, weil sie gestorben sind, sondern weil diese zwischenzeitlich zu anderen Firmen gewechselt sind. Demzufolge müsste sich das neue Entwicklerteam, dass das Programm des Kunden nicht programmiert hat, über mehrere Monate komplett neu in den Sourcecode einlesen und einarbeiten mit der unangenehmen Konsequenz, dass mit den vom Kunden gewünschten Erweiterungen praktisch ein komplett neues Programm entstehen würde. Wider Erwarten ist dem aber nicht so, weil die Programmierer in den Modulen sämtliche übergeordneten Klassen und Funktionen zu entsprechenden Objekten instanziieren, die sich jederzeit problemlos um weitere Funktionen, Attributen usw. ergänzen lassen, ohne dass die ursprünglichen Klassen-Instanzen „angefasst“ werden müssen! -

 

Beim Programm „micro_python-hallo_3-6.py wird die übergeordnete Klasse „Container_Klasse“ zunächst mittels des

 

·       Statements „Objekt_Container = Container_Klasse()

 

zum Objekt „Objekt_Container“ instanziiert und anschließend mittels des

 

·       Statements „Objekt_Container.Neue_ObjektVar =

’Ich bin neuer Content des Objekts 'Objekt_Container'!\n’ “

 

um die Objektvariable „Neue_ObjektVar“ nebst Content ergänzt (siehe roter Kasten):

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Die Funktion „Funktion_2(get_InputVar)“ innerhalb der Klasse „Klasse_2“ dient lediglich dazu, um aufzuzeigen, wie man den Variableninhalt der Objektvariable „Neue_ObjektVar“ quasi nach außerhalb des Hauptprogramms zur Anzeige bringt. -

 

Mit dem Programm „micro_python-hallo_3-7.py lässt sich zeigen, dass das Objekt „Objekt_Container“ zwar von der instanziierten Klasse „Container_Klasse“ alle Attribute usw. erbt, aber umgekehrt die Klasse „Container_Klasse“ leer ausgeht, wenn man das Objekt „Objekt_Container“ z.B. um die Objektvariable „Neue_ObjektVar“ nebst Textstring „Ich bin neuer Content des Objekts 'Objekt_Container'!“ erweitert:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Beim Instanziieren einer übergeordneten Klasse (oder Funktion), d.h. der Vererbung von Eigenschaften der Klasse an das entsprechende Objekt, ist es wie im richtigen Leben: erben tun immer nur die Hinterbliebenen, d.h. die Objekte, während der Spender selbst, d.h. die instanziierte Klasse, leer ausgeht, nicht bedacht wird, wenn sich das Objekt „vergrößert“. Bildlich gesprochen sozusagen.

 

Aber wie man anhand des Programms „micro_python-hallo_3-8.py sieht, gibt es, ebenfalls wie im richtigen Leben, einen Gerechtigkeitsausgleich, gibt es ein Geben und Nehmen zwischen dem Spender, d.h. der instanziierten Klasse und dem Empfänger, d.h. dem begünstigten Objekt (siehe roter Kasten im nachfolgenden Screenshot):

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wenn man also das Objekt „Objekt_Container“ z.B. um die Objektvariable „Neue_ObjektVar“ nebst Textstring „Ich bin neuer Content des Objekts 'Objekt_Container'!“ erweitert, dann erweitert sich im Umkehrschluss auch die Instanz-Klasse „Container_Klasse“ um den Variableninhalt der Klassenvariable „Neue_ObjektVar“:

 

In diesem Zusammenhang stellt sich abschließend die Frage, wie man das

 

·       Konstrukt „Objekt_Container = Container_Klasse

 

jetzt nennen soll.

 

Da von der übergeordneten Klasse „Container_Klasse“ kein neues Objekt „Objekt_Container“ instanziiert wird, handelt es sich bei dem neuen Konstrukt „Objekt_Container“ ebenfalls um eine übergeordnete, instanziierte Klasse! -

 

 

Was haben Objekte und das OOP mit dem „Internet of Things“ zu tun?

 

Wenn man einen Bekannten danach fragt, was ein Objekt ist oder sein könnte, dann wird er sagen, dass man einen Gegenstand als Objekt bezeichnen kann, weil man diesen auch anfassen kann. Wenn man also einen Gegenstand anfassen kann, dieser also gegenständlich ist, dann ist er ein Objekt. Und, wenn man einen Gegenstand anfassen kann, dann liegt er je nach Form und Struktur, d.h. Beschaffenheit, mehr oder weniger gut in der Hand. Demzufolge hat ein Gegenstand nicht nur ein Äußeres, eine Gestalt, die sich anfassen lässt, sondern auch Eigenschaften wie z.B. eine bestimmte Farbe, je nach Material auch einen bestimmten Geruch. Neue Möbel aus Pressspan z.B. riechen weniger nach Holz als viel mehr nach Formaldehyd, der die nächste Zeit erst noch ausdünsten muss, weshalb man anfangs öfters lüften sollte. Neuwagen, d.h. neue PKWs, werden seitens des Herstellers Duft optimiert, damit man das billige Plastik des Armaturenbretts nicht als störend empfindet. Ähnlich verhält es sich bei Limousinen der Ober- oder Luxusklasse, deren Autotüren bezüglich des Geräusches beim Schließen ebenfalls akustisch optimiert werden, indem man diese mit einem Hohlkörper versieht, dessen Resonanz beim Schließen der Tür einen kräftigen, sonoren und damit wertigen „Wumms“ erzeugt. -

 

Wenn man jemanden fragt, was „IoT“ bedeutet, dann fällt den meisten Mitmenschen dazu nichts ein, können diese mit der Abkürzung „Internet of Things (IoT)“ nichts anfangen. Auch dann nicht, wenn man ihnen die Abkürzung ins Deutsche übersetzt. Eigentlich müsste es ja auch „Internet der Dinge und Dienste“ heißen, weil die Dinge, d.h. die Objekte nicht wirklich intelligent sind. Objekte wissen deshalb erst dann wer und was sie sind, wenn man sie mit ihrer elektronischen und/oder digitalen Schnittstelle mit einem Computer, d.h. einem Server über das Internet verbindet. Der Server ist es nämlich, der dem Objekt „sagt“, was es für ein Objekt ist, was es für Eigenschaften (= Attribute) und Fähigkeiten (= Methoden) hat. Vorteilhaft ist es deshalb, wenn man selbst schon mal einen Server (Webserver, E-Mail-Server, NAS) betrieben hat. Demzufolge wissen auch viele nicht, dass ihre heimische FRITZ!Box nicht nur als WLAN-fähiger DSL-/VDSL-Router arbeitet, sondern eben auch als sogenannter NAS-Server im lokalen, d.h. heimischen Netzwerk (LAN) mittels dem sich Audio- und Videodateien auf den Desktop-PC, Notebook, das Tablet-PC oder Smartphone streamen lassen. Vorausgesetzt natürlich, dass man einen USB-Speicher oder eine USB-Festplatte mit Audio-/Videodateien, Fotos, Musik, aber auch Text- oder PDF-Dateien an die FRITZ!Box als NAS-Server anschließt. Dazu sollte man dann auch wissen, was „NAS“ bedeutet, nämlich „Network Attached Storage“ im Sinne eines netzwerkfähigen USB-Speichers im lokalen Netzwerk (LAN) oder Internet („MyFRITZ!“). -

 

Auch wenn viele Menschen nicht wissen, was „IoT“ bedeutet, so gibt es doch einige von ihnen, die mit „Industrie 4.0“ oder „Arbeit 4.0“ etwas anfangen können. Diesbezüglich wäre aber wichtig zu wissen, dass alle Begriffe mit ein und derselben Sache zu tun haben, nämlich der „Vierten, industriellen Revolution!“. Es ist also nur eine Frage der Zeit, wann die FRITZ!Box auch zum heimischen IoT-Server wird, der Kühlschrank, Kaffeemaschine, Waschmaschine, Rollladensteuerung, die Steuerung des farbigen Lichts im smarten Zuhause miteinander vernetzt und miteinander kommunizieren lässt. So wie es aber im Moment aussieht, wird Google mit „Google Nest Hub“, der smarten, sprachgesteuerten Vernetzung der heimischen Umgebung das Rennen machen. Nicht zuletzt wegen des vielen Kapitals, das Google in Google Nest investieren kann, sondern auch wegen des Betriebssystems von Google Android mit dem Google Assistenten. Dazu muss man wissen, dass die „Alexa“-Konkurrenz von Amazon die weniger gute „Bing“-Suchmaschine von Microsoft verwendet und eben über kein universelles „Android“-Betriebssystem nebst künstlicher Intelligenz in Form des „Google Assistenten“ verfügt. -

 

 

Kraftfahrzeuge nicht nur als Objekt der Begierde

 

Wenn es also darum geht, in die Objekt orientierte Programmierung (OOP) einzusteigen, dann wird das am besten gelingen, wenn die Objekte leben, lebendig und anschaulich sind. Oder aber umstritten, wie z.B. die SUVs, die wegen ihrer vielen PS und des hohen Schadstoffausstoßes extrem klimaschädlich und gesundheitsgefährlich sind.

 

Kurz und gut, bei den PKWs, wie z.B. Limousinen, Sportwagen, SUVs, Kleintransportern, Oldtimern, und LKWs geht es, wie der Name schon sagt, um (Kraft-) Fahrzeuge, die über einen eigenen Antrieb verfügen und von Otto-, Diesel- oder Elektromotoren angetrieben werden. Demzufolge gibt es eine Klasse „PKW“ und eine Klasse „LKW“ und die darüber befindliche Basisklasse „Fahrzeuge“:

 

# Programm micro_python-hallo_3-9.py

 

# Definition der Basisklasse ’Fahrzeuge’

class Fahrzeuge:

   

    class PKW:

        pass

   

    class LKW:

        pass

   

    pass

 

 

Alle Fahrzeuge verfügen über die grundlegende Eigenschaft, dass sie beschleunigen und bremsen können. Demzufolge positionieren wir die Methoden „beschleunigen()“ und „bremsen()“ oberhalb der Klassen „PKW“ und „LKW“:

 

# Programm micro_python-hallo_3-9.py

 

# Definition der Basisklasse ’Fahrzeuge’

class Fahrzeuge:

   

    def darf_beschleunigen():

        return

 

    def muss_bremsen():

        return

 

    class PKW:

        pass

   

    class LKW:

        pass

   

    pass

 

# -------------------------------------------------- Hauptprogramm --------------------------------------------------

 

print("Was tut sich in der Klasse 'Fahrzeuge'?", type(Fahrzeuge))

 

 

Wenn man das Programm „micro_python-hallo_3-9.py startet, dann stellt man fest, dass sich in der Klasse „Fahrzeuge“ noch nichts tut, was ja auch nicht weiter verwunderlich ist, weil es ja noch keine Fahrzeuge gibt.

 

Wenn wir jetzt zwei PKWs der Marke „VW“ und „BMW“ kaufen und dem Fuhrpark hinzufügen, dann stellt sich die Frage, wie wir diese der Klasse „PKW“ hinzufügen. Naheliegend wäre z.B. dass wir diese innerhalb der Klasse „PKW“ namentlich aufführen, im Sinne von erwähnen (siehe Programm „micro_python-hallo_3-10.py):

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Aber die Namensangabe in Form des Textstrings „Volkswagen“ der Variablen „vw“ wäre dann nichts anderes als ein Namensschild, eine Namensangabe oder ein Namenslabel (= Etikett, Aufkleber, Aufdruck). Damit wäre dann gerade einmal der Name als Attribut (= Eigenschaft) eines Objektes vom Typ „PKW“ festgelegt. Aber bei der Variablen „vw“ handelt es sich um eine Stringvariable und noch nicht um ein Attribut zum Objekt „vw“ vom Typ „PKW“.

 

Diesbezüglich müssen wir also das Label „Volkswagen“ zu einem Attribut des Objektes „vw“ machen. Und zwar mit den Statements

 

·       vw = PKW() und

·       vw.label = “Volkswagen“

 

Dabei wird die Objektvariable „vw“ mit dem ersten Statement zu einem Bestandteil der Klasse „PKW“. Und mit dem zweiten Statement, das das erste Statement zwingend voraussetzt, wird die Stringvariable „label“ zum ersten Attribut des Objektes „vw“ der Klasse „PKW“.

 

In diesem Zusammenhang stellt sich dann gleich die Frage, an welcher Stelle wir die beiden Statements im Programmkode unterbringen müssen.

 

Wenn es also ein neues Objekt „vw“ der Klasse „PKW“ geben soll, dann muss die Klasse „PKW“ zuvor schon existent sein. Demzufolge müssen die beiden Statements als Programmkode ans Ende der Klasse „Fahrzeuge“ wie folgt positioniert werden:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wenn man sich die Bildschirmanzeige des Programm „micro_python-hallo_3-11.py anschaut,

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

dann bestätigt sich, dass das Objekt „vw“ tatsächlich zur Klasse „PKW“ gehört.

 

Im Programm „micro_python-hallo_3-12.py wird die Anzeige einzelner Attribute „label“, „kfztype“, „leistung“ der Objekte „vw“ und „bmw“ ans Ende der Klasse „Fahrzeuge“ verfrachtet. Das Bemerkenswerte dabei ist, dass die Klasse „PKW“ nur gebraucht wird, um diese zu deklarieren, sodass in dieser selbst kein Programmkode generiert wird! Demzufolge dient die Klasse „PKW“ nur dazu, um die Objekte „vw“ und „bmw“ anlegen zu können, indem die Klasse selbst instanziiert wird, sodass diese zur Instanz für die Objekte selbst wird:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Der Nachteil beim obenstehenden Programm „micro_python-hallo_3-12.py ist noch der, dass man sich die Attribute „label“, „kfztype“ und „leistung“ nur einzeln anschauen bzw. zur Anzeige bringen kann. Vorteilhafter wäre es natürlich, wenn man sich die Attribute auch als Ganzes, z.B. in Form einer Auflistung, anzeigen lassen könnte.

 

Beim Programm „micro_python-hallo_3-13.py werden die einzelnen Attribute „label“, „kfztype“ und „leistung“ in der „tuple“-Liste „attribute“ zusammengefasst. Und zwar für jedes der Objekte „vw“ und „bmw“:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Beim Programm „micro_python-hallo_3-14.py werden die Attribute „marke“, „label“, „kfztype“ und „leistung“ nebst der „tuple“-Liste „attribute“ in die Funktion „festlegen_Attribute(self, marke, parameter)“ ausgelagert:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Dabei werden Funktion „festlegen_Attribute(self, marke, parameter)“ insgesamt drei Parameter mit auf den Weg gegeben, damit sich „return“-Rückgabe der Funktion flexibel handhaben lässt. Dabei legt man mit dem ersten Parameter „self“ fest, welchem Objekt „vw“ oder „bmw“ welche Attribute zugewiesen werden sollen.

 

Der zweite Paramter „marke“ dient als Unterscheidungsmerkmal, welchem Objekt („vw“ oder „bmw“) welche Attribute „marke“, „label“, „kfztype“ und „leistung“ nebst der „tuple“-Liste „attribute“ dem Objekt mit auf den Weg gegeben werden sollen.

 

Mit dem dritten Parameter „0“, „1“, …, „4“ wird dann festgelegt, welches Attribut mittels „return“-Statement aus der Attributeliste „Attribute“ zurückgegeben werden soll. Dabei steht „0“ für „alle Attribute“ sollen zurückgegeben werden, „1“ bis „4“ jeweils nur „ein Attribut“ entsprechend der Position in der Attributeliste „Attribute“:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Als nächstes lassen wir den Golf 1.0 TSI mit 66 kW von 0 auf 100 km/h beschleunigen. Dazu braucht das Fahrtzeug eine Beschleunigungszeit von ta = 9,9 s.

 

Dabei berechnet sich die Beschleunigung mittels der Formel v = a * t     

 

a = v / t = 100 km/h / 9,9 s = 100 * 103 m/3600 s ) / 9,9 s = 100 * 1 m/3,6 s / 9,9 s = 100 m / 3,6 s / 9,9 s = 2,81 m/s2 

 

Wenn man den Golf weiter bis zur Endgeschwindigkeit vEnd mit

 

vEnd = 196 km/h = 196 * 1000 m / 3600 s = 196 * 1000 m / 3,600 s = 196 m / 3,6 s = 54,4 m/s

 

beschleunigen lässt, dann hat er bis zum Erreichen der Höchstgeschwindigkeit die Zeitdauer t = 19,4 s zurück gelegt:

 

v = a * t      t = v / a = 54,4 m/s / 2,81 m/s2 = 19,4 s

 

Während dieser Zeit hat er eine Entfernung von

 

v = s / t      s = v * t = 54,4 m/s * 19,4 s = 1.055,36 m = 1,1 km zurück gelegt. -

 

Kennen Sie den Unterschied zwischen einer gleichförmigen und ungleichförmigen Beschleunigung? Bei einer gleichförmigen Beschleunigung ist die Beschleunigung selbst immer gleich groß, d.h. konstant, sodass sie sich demzufolge nicht ändert. Das Verblüffende daran ist nun, dass das Fahrzeug beim Beschleunigen immer schneller wird, mehr Fahrt aufnimmt, obwohl sich an der Beschleunigung mit agleich = konstant selbst nichts ändert, weil diese ja konstant ist. Bezüglich der Beschleunigung könnte man nämlich aus der Beobachtung und aus der Erfahrung heraus meinen, dass das Fahrzeug nur deshalb schneller wird, weil es immer stärker beschleunigt. Aber genau das ist nicht der Fall, weil zu der aktuellen (Momentan-) Geschwindigkeit durch die Beschleunigung fortwährend noch ein weiterer Geschwindigkeitszuwachs  - nicht Beschleunigungszuwachs -  von v = agleich * t hinzu kommt: v = v0 + a * t mit v0 = Anfangsgeschwindigkeit.

 

Bei einer ungleichförmigen Beschleunigung ändert sich die Beschleunigung fortwährend, sodass diese eben nicht mehr konstant ist wie bei der gleichförmigen Beschleunigung. Bei einer Rakete zum Beispiel ändert sich die Beschleunigung fortwährend, sodass diese größer wird, die Rakete mehr und mehr stärker beschleunigt, weil sich die Kraftstofftanks entleeren und die Rakete dabei an Gewicht und damit an Masse verliert.

 

So, nachdem wir nun wissen, wie eine gleichförmige Beschleunigung funktioniert und sich recht einfach berechnen lässt, machen wir uns daran und programmieren wir diese innerhalb der Funktion „darf_beschleunigen()“:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wenn man sich das Programm „micro_python-hallo_3-15.py anschaut, dann fällt sofort auf, dass zu Beginn des Programms die beiden Module „time“ und „_thread“ importiert werden, um sie später im Hauptprogramm nutzen zu können. Dabei stellt sich gleich die Frage, was ein _thread ist (man beachte den Unterstrich!). Wenn man „thread“ wortwörtlich übersetzt, dann heißt es auf Deutsch „Faden“:

 

>> In der Informatik bezeichnet Thread [θɹɛd] (englisch thread, ‚Faden‘, ‚Strang‘) auch Aktivitätsträger oder leichtgewichtiger Prozess genannt – einen Ausführungsstrang oder eine Ausführungsreihenfolge in der Abarbeitung eines Programms. Ein Thread ist Teil eines Prozesses.

Es wird zwischen zwei Arten von Threads unterschieden:

1.   Threads im engeren Sinne, die sogenannten Kernel-Threads, laufen ab unter Steuerung durch das Betriebssystem.

2.   Im Gegensatz dazu stehen die sogenannten User-Threads, die das Computerprogramm des Anwenders komplett selbst verwalten muss. << (Quelle: Wikipedia)

 

Sicherlich haben Sie schon etwas von „Multitasking“ gehört. Dabei ist aber nicht das Multitasking der Frauen gemeint, die vermeintlich mehrere Aufgaben so ganz nebenbei bewerkstelligen können. So weit ich informiert bin und richtig gelesen habe, gibt es beim Menschen, also weder bei Frauen noch Männern, echtes Multitasking. Man kann zwar beim Arbeiten, Lösen der Hausaufgaben oder z.B. Programmieren nebenbei Musik hören und damit die andere Gehirnhälfte aktivieren, sodass sich bei Lernprozessen beide Gehirnhälften besser untereinander vernetzen und Gelerntes ggf. besser speichern.

 

Ein kleines Beispiel bzw. Witz für das unterschiedliche Arbeiten beider Gehirnhälften: „Bei einem Stotterer brennt zu Hause die Küche, weil er das Braten der Bratwurst zu lange unbeaufsichtigt ließ, sodass sich das Fett in der Bratpfanne entzündete. Als er mit der Notrufnummer 112 die Feuerwehr zur Hilfe rufen will, fällt ihm ein, dass er wegen der Aufregung des Küchenbrandes und seiner Stotterei keinen richtigen Satz herausbekommt, sodass ihn der Feuerwehrmann am anderen Ende der Leitung absolut nicht versteht, wohin sie fahren und den Brand löschen soll. Zum Glück fällt ihm aber rechtzeitig ein, dass er als Stotterer einfach nur zu singen braucht, um sich verständlich mitzuteilen, da beim Singen die andere Gehirnhälfte aktiv ist und Stotterer beim Singen eben nicht stottern! Also ruft der Stotterer die Feuerwehr an und singt ins Telefon: ‚Es breeeeennnnntttt, es breeeennnnntttt, es breeeennnt!’ Da tönt es am anderen Ende der Telefonleitung: ‚Fiderallala, fiderallala, fiderallalalala!’ und der Hörer wurde aufgelegt.“

 

Wenn also der Stotterer beide Gehirnhälften benutzt, indem er singt und dabei quasi Multitasking betreibt, ist dies bei dem Feuerwehrmann am Telefon genau nicht der Fall.

 

Multitasking beim „Windows-“ oder „Linux-“ Betriebssystem bedeutet, dass sich der (Rechen-) Prozessor aufteilt und quasi gleichzeitig mehrere Aufgaben, d.h. Programme ausführt und bedient. In Wirklichkeit aber wird das Multitasking nur dem Anwender vorgegaukelt.

 

Dazu muss man wissen, dass Prozessorkerne nebst Rechenwerk (ALU = engl. „Arithmetic Logic Unit“, d.h. „Arithmetische Logikeinheit“) sehr schnell rechnen können, weil sie nur zwei Finger anstelle von zehn besitzen, d.h. binär mit Nullen und Einsen rechnen.

 

Demzufolge gibt es für den Rechenknecht, d.h. die CPU (= engl. „Central Processor Unit“, d.h. Zentrale Prozessoreinheit“) eine sogenannte Zeitscheibe, die sich beim Bewältigen mehrerer Aufgaben entsprechend aufteilt und zwar ähnlich einer unterteilten Erdbeertorte.

 

Praktisch bedeutet dies, dass sich der Prozessor zeitlich immer nur einen kurzen Moment einer Aufgabe widmet und bezüglich der 360 Grad Zeitscheibe im Laufe eines Umlaufs dabei aber insgesamt mehrere Aufgaben quasi gleichzeitig (aus der Sicht des Anwenders), in Wirklichkeit aber nacheinander (aus der Sicht des Prozessors und der Zeitscheibe) bearbeitet.

 

Ähnlich verhält es sich bei einem oder mehreren Threads bei der Python-Programmierung. Anschaulich könnte man sagen, dass das Threading bei einem Python-Programm dem Multitasking eines Betriebssystems entspricht. Und das ist schon eine tolle Sache! Man kann im Python-Programm einen Prozess anstoßen, um diesen dann parallel im Hintergrund laufen und ausführen zu lassen.

 

Wenn man z.B. einen Bewegungssensor ständig abfragt, ob es eine Bewegung gibt oder nicht, dann soll dieser Vorgang eben nicht ständig das Hauptprogramm stören und unterbrechen. Aus diesem Grund lässt man dann die Abfrage des Bewegungssensors in einem Thread im Hintergrund laufen. Erst, wenn es wirklich eine maßgebliche Bewegung gibt, wird vom Thread ein Ereignis gemeldet, das vom Hauptprogramm entgegen genommen und bearbeitet wird. Aber das Ereignis gesteuerte Programmieren scheint dann doch ein Thema für sich zu sein, dem es sich zu gegebener Zeit zu widmen gilt. -

 

Zurück zum Programm „micro_python-hallo_3-15.py und zur Methode „darf_beschleunigen()“ bei der die Endgeschwindigkeit „v_ende“ anhand der der Beschleunigung a = 2,81 m/s^2 des VW Golf 8, Typ 1.0 TSI und der Beschleunigungszeit von 19,4 s berechnet wird. Dabei wird die Beschleunigungszeit des VW Golf der Einfachheit halber von 100 km/h bis zum Erreichen der Höchstgeschwindigkeit von 196 km/h hochgerechnet und dabei so getan als würde der VW Golf durchgehend gleichförmig, d.h. konstant beschleunigt.

 

Da wir es bei dem Programm „micro_python-hallo_3-16.py mit mehreren Objekten und zwar dem Objekt „vw“ und „bmw“ der Klasse „PKW“ zu tun haben und bei diesen unterschiedliche Fahrzeugparameter verwendet werden, ist es an der Zeit, dass wir die entsprechenden Fahrzeugattribute in der Methode „festlegen_Attribute(self, marke, parameter)“ wie folgt speichern:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Da es zu der Klasse „PKW“ die beiden Objekte „vw“ und „bmw“ gibt, spricht man von der Methode „festlegen_Attribute(self, marke, parameter)“! Dabei wird die „tuple“-Attributeliste „attribute“ zunächst lokal innerhalb

der Methode abgespeichert und später beim Methodenaufruf mittels des

 

·       Statements self.attribute = attribute“

 

einem der beiden Objekte „vw“ oder „bmw“ zugewiesen, sodass das jeweilige Objekt später über entsprechende Eigenschaften verfügt!

 

Mit dem

 

·       Statement „return(attribute_Objekt)“

 

erfolgt dann der Rücksprung wieder in die Klasse „Fahrzeuge“, wo die Attributeliste des jeweils aufgerufenen Objektes „vw“ oder „bmw“ innerhalb der Klasse gespeichert wird und dieser damit zur Verfügung steht. -

 

Im Programm „micro_python-hallo_3-17.py wird die Attributeliste um die Attribute „beschleunigung“ und „max_geschwindigkeit“ erweitert, sodass sich mit diesen rechnen und in der Methode „darf_beschleunigen()“ die Beschleunigungsdauer und die dabei erreichte Höchstgeschwindigkeit berechnen lassen.

 

Damit sich der

 

·       Thread „_thread.start_new_thread(darf_beschleunigen, ( ) )” zusammen mit der

 

·       Methode darf_beschleunigen()”

 

vom Hauptprogramm aus aufrufen lässt, müssen wir zuvor die Attributeliste der Klasse „Fahrzeuge“ für das Hauptprogramm verfügbar machen. Der Knackpunkt dabei ist der, dass die Übergabeparameter der Methode „darf_beschleunigen()“ nur in Form einer „tuple“-Liste „( )“ beim Starten des Threads übergeben werden dürfen:

 

·       Thread „_thread.start_new_thread(darf_beschleunigen,

(beschleunigungKFZ, max_geschwindigkeitKFZ) )”

 

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man anhand des Programms „micro_python-hallo_3-18.py sieht, geht es auch kompakter:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wenn also die Daten der „tuple“-Attributeliste „attribute“ nicht explizit im Hauptprogramm benötigt werden, dann muss man diese auch nicht zwingend vor dem Starten des Threads für das Hauptprogramm verfügbar machen (siehe roter Kasten im obenstehenden Bild).

 

Im vorherigen Programm „micro_python-hallo_3-17.py“ wurde die „tuple“-Attributeliste „attribute“ hauptsächlich nur deshalb für das Hauptprogramm verfügbar gemacht, weil es darum ging herzufinden, wie man das Ganze handwerklich/programmiertechnisch bewerkstelligen muss und umsetzen kann, da Daten-/Variableninhalte usw. innerhalb einer Methode einer Klasse sehr gut nach außen hin zum Hauptprogramm gekapselt sind!

 

Schwierig, da neu und ungewohnt, ist es auch deshalb, weil wir die beiden Objekte „vw“ und „bmw“ der Klasse „PKW“ zugeordnet haben, die wiederum zur übergeordneten Klasse „Fahrzeuge“ gehört.

 

Das ist dann auch der Grund dafür, dass man dem Objekt „vw“ oder „bmw“ die Angabe der übergeordneten Klasse „Fahrzeuge“ voranstellen muss:

 

·       Fahrzeuge.darf_beschleunigen

 

·       Fahrzeuge.festlegen_Attribute(Fahrzeuge.vw, "VW", 4)

 

… und nicht:

 

·       vw.darf_beschleunigen

 

·       vw.festlegen_Attribute(vw, "VW", 4)

 

Beim Programm „micro_python-hallo_3-19.py geht es darum, dass wir das Hauptprogramm aufräumen, indem wir das

 

·       Statement „_thread.start_new_thread(darf_beschleunigen, ( … ) )”

 

ans Ende der Klasse „Fahrzeuge“ auslagern:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wenn man sich die beiden „thread“-Statements im Programm „micro_python-hallo_3-18.py (siehe im Bild weiter oben) und im Programm „micro_python-hallo_3-19.py (siehe obenstehendes Bild) anschaut und miteinander vergleicht, dann fällt sofort auf, das letzteres am einfachsten und übersichtlichsten ist. -

 

Das Statement „time.sleep(5)“ am Ende des Hauptprogramms ist notwendig, damit der Thread eventuell auf andere Threads wartet und nicht sofort beendet wird. Alle Threads eines Programms werden nämlich sofort abgebrochen, wenn das Hauptprogramm sein Ende erreicht hat. Mit dem Modul „threading“ lassen sich bessere Methoden anwenden, um einen Thread auf das Ende eines anderen warten zu lassen. -

 

Mit der Objekt orientierten Programmierung (OOP) haben wir im Programm „micro_python-hallo_3-20.py zunächst die beiden Objekte „vw“ und „bmw“ der Klasse „PKW“ erzeugt, die wiederum zur Oberklasse „Fahrzeuge“ gehört. Diesen Vorgang nennt man übrigens Instanzen einer Klasse erzeugen. -

 

Wie wir bereits wissen, verfügen Objekte über Eigenschaften, die man bei der OOP als Attribute bezeichnet:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Als ein beispielhaftes Attribut sei hier die Variable „beschleunigung_a“ des VW Golf 1.0 TSI benannt, der mit 2,81 m/s^2 auf 100 km/h beschleunigt. Mittels der Formel v = a * t lässt sich dann die dazu erforderliche Beschleunigungszeit bzw. -dauer tB1 wie folgt berechnen:

 

tB1 = v / a = 100 km/h / 2,81 m/s2 = 100 1000 m/3600 s / 2,81 m/s2 = 1000 m / 3600 s / 2,81 m/s2

     = 27,78 / 2,81 s = 9,89 s

 

Da die Maximalgeschwindigkeit des VW Golf 1.0 TSI aber 196 km/h beträgt, lässt sich dieser auch über die 100 km/h hinaus weiter bis zum Erreichen der Höchstgeschwindigkeit beschleunigen, sodass sich die Beschleunigungszeit entsprechend vergrößert:

 

tB2 = v / a = 196 km/h / 2,81 m/s2 = 196 1000 m/3600 s / 2,81 m/s2 = 1960 m / 3600 s / 2,81 m/s2

     =  54,44 / 2,81 s =  19,37 s

 

Wie man unschwer sieht, gibt es zum Objekt „vw“ und „bmw“ nicht nur statische Attribute, sondern bezüglich des Fahrens und der Fahrphysik auch dynamische wie z.B. die Beschleunigungszeit von 0 auf 100 km/h bzw. 196 km/h. Dass sich ab etwa 100 km/h der Luftwiderstand des Objektes erhöht und das Fahrzeug demzufolge länger braucht, um die Höchstgeschwindigkeit von 196 km/h zu erreichen, versteht sich von selbst, soll aber der Einfachheit halber unberücksichtigt bleiben.

 

Bezüglich der fahrdynamischen Attribute gibt es im Wesentlichen drei Gruppen und zwar:

 

Ein Auto

 

·       steht, wartet,

·       fährt vor- oder rückwärts,

·       beschleunigt oder bremst.

 

Dabei hat das Auto beim Vor- oder Rückwärtsfahren jeweils eine Anfangsgeschwindigkeit v0, eine mittlere Geschwindigkeit vMittel, eine Momentan- oder Maximalgeschwindigkeit vmax.

 

Beim Beschleunigen oder Verzögern/Bremsen gibt es die Beschleunigung a, die Beschleunigungsdauer t und den Geschwindigkeitszuwachse v am Ende der Beschleunigung. Dabei hat die Beschleunigung a beim Verzögern/Bremsen sowie bei der Geschwindigkeitsabnahme einen negativen Koeffizienten.

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man anhand des Programms „micro_python-hallo_3-21.py sieht, lassen sich die dynamischen Attribute noch weiter untergliedern:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Allerdings hat das Programm „micro_python-hallo_3-21.py“ noch einen entscheidenden „Schönheitsfehler“. Und zwar den, dass die Attributslisten in den roten Kästen von den booleschen Attributen im grünen Kasten überschrieben werden (siehe obenstehendes Bild)!

 

Da wir aber noch lernen müssen, wie man von außen auf die Liste mit den dynamischen Attributen und deren Variablen zugreifen kann, entscheiden wir uns im Programm „micro_python-hallo_3-22.py zunächst für die einfachere Variante mit dem grünen Kasten:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wenn man sich dann noch die Bildschirmausgabe des Programms „micro_python-hallo_3-22.py anschaut,

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

dann wird sofort klar, dass die dynamische Attributeliste „dyn_Attribute“ (siehe grüner Kasten im obenstehenden Screenshot) nicht besonders selbsterklärend bzw. anschaulich ist.

 

Bei der Frage „Ist VW größer als BMW?“ mit der Antwort „True“ handelt es sich nicht um einen Größenvergleich beider Automobilhersteller, sondern vielmehr um die

 

·       Abfrage „Fahrzeuge.vw.dyn_Attribute > Fahrzeuge.bmw.dyn_Attribute.

 

Dabei werden die dynamischen Attribute der beiden Objekte „vw“ und „bmw“ miteinander verglichen. Und zwar als Ganzes, d.h. in Form der Liste, könnte man meinen. Aber in Wirklichkeit wird nur die Reihenfolge, d.h. die programmiertechnische Abfolge der beiden Objekte „vw“ und „bmw“ miteinander verglichen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Mit dem Programm „micro_python-hallo_3-23.py wird die Anzeige der dynamischen Attribute schon wesentlich aussagekräftiger und anschaulicher:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Beim Programm „micro_python-hallo_3-24.py werden die Statements zwecks Anzeige der dynamischen Attribute aus dem Hauptprogramm entfernt und am Ende der Klasse „Fahrzeuge“ wieder eingefügt:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Als nächstes werden wir im Programm „micro_python-hallo_3-25.py konkreter, indem wir mehr ins Detail gehen und Berechnungen hinsichtlich der Beschleunigung, der Beschleunigungsdauer und der dabei erreichten Geschwindigkeit anstellen. Dabei kommen dann auch die dynamischen, d.h. veränderlichen Attribute-Listen „bewegt_sich“, „beschleunigt“ und „geschwindigkeit“ der Objekte „vw“ und „bmw“ zum Einsatz:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man anhand des nachfolgenden Screenshots sieht, beschleunigen beide (Fahrzeug-) Objekte „vw“ und „bmw“ insgesamt 4,94 Sekunden lang und erreichen wegen des unterschiedlich großen Beschleunigungsvermögens im gleichen Zeitrum auch dementsprechend unterschiedlich große Geschwindigkeiten von 50 km/h bzw. 58,2 km/h:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man bei der obenstehenden Berechnung und der dazugehörigen Anzeige sieht, erreicht der „VW Golf 1.0 TSI“ die innerörtliche Höchstgeschwindigkeit von 50 km/h nach 4,94 Sekunden.

 

Diesbezüglich erreicht der schnellere „BMW 1 F40“ wegen seiner größeren Beschleunigung von 3,27 m/s2 die „50 km/h“-Marke in deutlich kürzerer Zeit:

 

v = a * t             t = v / a = 50 km/h / 3,27 m/s2 = 50 * 1000 m/3600 s / 3,27 m/s2 = 4,25 s

 

Da es sich bei der Beschleunigung eines PKWs um einen temporären Vorgang, d.h. Ereignis handelt, macht es, wenn es um die Objekt und Ereignis orientierte Programmierung geht, wenig Sinn, wenn man einen solchen dynamischen und zeitlich befristeten Vorgang statisch und zeitlich bis zur Unendlichkeit bzw. bis zum Stromausfall programmiert. Mit anderen Worten: Wenn wir das Programm „micro_python-hallo_3-25.py starten, dann wird jedes Mal der Beschleunigungsvorgang ausgelöst, egal, ob dieser irgendwann einmal schon stattgefunden hat oder nicht.

 

 

Objekte und deren Attribute mit Verfallsdatum

 

Zwar lassen sich Beschleunigungsvorgänge beliebig oft wiederholen, sind aber wegen der jeweils unterschiedlichen Verkehrssituationen und Reaktionen auf diese individuell unterschiedlich und damit für sich genommen einmalig.

 

Um deutlich zu machen, dass es sich bei einem Beschleunigungsvorgang um einen zeitlich befristeten und in seiner Individualität und Einmaligkeit einzigartig stattfindenden Vorgang handelt, werden wir diesem symbolisch ein Verfallsdatum geben. Und zwar in dem Sinne, dass der Beschleunigungsvorgang deklariert, initialisiert, angestoßen, abgearbeitet, beendet und anschließend gelöscht wird.

 

Zum Beschleunigen braucht es im vorliegenden Fall ein Fahrzeug bei dem es sich programmiertechnisch um ein Objekt handelt, das über verschiedene statische und dynamische Eigenschaften im Sinne von Attributen verfügt. Beim Programm „micro_python-hallo_3-26.py wenden wir erstmals einen sogenannten „Konstruktor“ als besondere Methode (= Funktion innerhalb einer Klasse) an, um dem Objekt PKW eine Lebensdauer, sozusagen ein Verfallsdatum, zu verpassen. Dabei handelt es sich nicht wirklich um ein kalendarisches Verfallsdatum, sondern vielmehr um eine Aktion bei der das entsprechende Objekt verfällt, d.h. das Zeitliche segnet, wenn es seinen Zweck erfüllt hat.

 

Was aber ist ein „Konstruktor“? Im Lateinischen bedeutet „con“ wortwörtlich „mit“. Demzufolge geht es beim Konstruktor oder Konstrukt um etwas Zusammenhängendes, etwas Zusammengesetzes. Ein Konstrukt fügt also bestimmte Dinge bzw. Attribute zum Objekt hinzu. Die Aufgabe von Konstruktoren ist es also, Objekte in einen definierten Anfangszustand zu bringen und so benötigte Ressourcen zu reservieren, sofern diese zum Zeitpunkt der Objekterstellung bereits bekannt sind:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man im obenstehenden Quellkode sieht, wird die Geschwindigkeit „a_geschwindigkeit“ als Funktion der Beschleunigung als auch der Beschleunigungsdauer berechnet und mittels „return“-Statement zurückgegeben, sodass der nachfolgende Konstruktor „__str__(a_geschwindigkeit)“ auf das Ergebnis zugreifen und dieses auf den Bildschirm anzeigen kann:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Mit dem Konstruktor „__str__(a_geschwindigkeit)“ kann man sich also jederzeit anzeigen lassen, ob das Attribut „a_geschwindigkeit“ noch existent ist oder nicht. Im Falle aber, dass das Attribut „a_geschwindigkeit“ nicht mehr existiert, weil es zwischenzeitlich gelöscht wurde, gibt es eine entsprechende Fehlermeldung.

 

Was jetzt noch fehlt ist der Konstruktor „__del__()“ mit dem sich z.B. das Attribut „a_geschwindigkeit“ löschen lässt. Dazu muss noch ergänzt werden, dass sich im Konstruktor „__del__()“ selbst nur Attribute löschen lassen, nicht jedoch das dazugehörige Objekt „vw“ als Instanz der Klasse „PKW“:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Da wir die beiden Objekte „vw“ und „bmw“ nicht antasten wollen, legen wir im Hauptprogramm das neue Objekt ego als Instanz der Klasse „Fahrzeuge“ (nicht der Klasse „PKW“) an. Und zwar mit dem

 

·       Statement „ego = Fahrzeuge(a_dauer, a_beschleunigung)“

 

Da wir das Objekt „ego“ als Instanz der Klasse „Fahrzeuge“ beschleunigen lassen wollen und dazu dann auch die Beschleunigung berechnen müssen, geben wir der Klasse noch die beiden Variablen „a_dauer“ für die Beschleunigungsdauer und „a_beschleunigung“ für die Beschleunigung des Fahrzeugs „ego“ mit auf den Weg.

 

Dabei sind die beiden Variablen „a_dauer“ und „a_beschleunigung“ keine Attribute des Objekts „ego“, sondern Variablen der Klasse „Fahrzeuge“!

 

Dabei stellt sich dann gleich die Frage, wo und wie sich die Geschwindigkeit als Funktion der Beschleunigung und der Beschleunigungsdauer berechnen lässt. Nämlich im Konstrukt „__init__(self, a_beschleunigung, a_dauer)“ innerhalb der Klasse „Fahrzeuge“:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Bei der Berechnung der Geschwindigkeit „a_geschwindigkeit“ ist besonders interessant, dass das Konstrukt „__init__(self, a_beschleunigung, a_dauer)“ wider Erwarten nicht explizit aufgerufen/gestartet werden muss, um die Geschwindigkeit zu berechnen, da das Konstrukt, d.h. die besondere Methode, beim Programmstart automatisch als Erstes ausgeführt wird (siehe Programm „micro_python-hallo_3-27.py). Das gilt aber auch für alle anderen Methoden innerhalb der Klasse „Fahrzeuge“. Auch diese starten sich automatisch beim Programmstart.

 

Beim Programm „micro_python-hallo_3-28.py kommen erstmalig zwei neue Statements zum Einsatz und zwar das

 

·       Statement „del ego.a_geschwindigkeit und das

 

·       Statement „del ego“.

 

Dabei wird beim ersten Statement „del ego.a_geschwindigkeit das Attribut „a_geschwindigkeit“ des Objektes „ego“ aus der Klasse „Fahrzeuge“ gelöscht. Diesbezüglich steht nämlich die engl. Abkürzung „del“ für „delete“, d.h. löschen, entfernen.

 

Das Statement „del ego.a_geschwindigkeit findet sich mit „#“ auskommentiert im Konstrukt „__del__()“ der Klasse „Fahrzeuge“. Und zwar auskommentiert deshalb, weil es bei der Aktivierung/Umsetzung bei der weiteren Programmausführung des Sourcecodes zu einer entsprechenden Fehlermeldung führt.

 

Das Statement „del ego“ findet sich mit „#“ auskommentiert im Hauptprogramm und sorgt dafür, dass das neue Objekt „ego“ der Instanz „Fahrzeuge“ komplett gelöscht wird, sodass dieses demzufolge bei der weiteren Programmausführung nicht mehr zur Verfügung steht und beim Aufruf der nachfolgenden Konstrukte „Fahrzeuge.__del__()“ und „Fahrzeuge.__str__()“ im Hauptprogramm zu einer entsprechenden Fehlermeldung führt. Das ist dann auch der Grund dafür, weshalb es zunächst im Quellkode mit „#“ auskommentiert wurde.

 

Auf Dauer sind die Fehlermeldungen natürlich sehr lästig, da ja schließlich der Programmablauf unterbrochen wird. Beim Programm „micro_python-hallo_3-29.py gibt es diesen Nachteil nicht mehr, da Fehlermeldungen, die den Programmablauf unterbrechen, indem diese das entsprechende Programm kurzerhand beenden, mittels „Versuch und Irrtum“ unterbunden werden. Genau genommen müsste es aber „Versuch und Ausnahme“, engl. „try and exception“, heißen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Wie man im obenstehenden Programmkode sieht, sorgt das

 

·       Statement „del self.a_geschwindigkeit 

 

dafür, dass das Attribut „a_geschwindigkeit“ des Objektes „ego“ gelöscht wird, sodass sich die Geschwindigkeit nicht mehr im

 

·       Statement „print("Die Geschwindigkeit beträgt noch immer:", self.a_geschwindigkeit, "km/h\n")“

 

anzeigen lässt und es im Normalfall aufgrund einer entsprechenden Fehlermeldung zum Programmabbruch käme. Es kommt aber nicht zur Fehlermeldung nebst Programmabbruch, da dieser durch das „except“-Statement (= „ausgenommen“-Statement) abgefangen wird und stattdessen die Meldung „Das Attribut 'a_geschwindigkeit' existiert NICHT mehr!“ angezeigt wird (siehe obenstehendes Bild).

 

Selbstverständlich lässt sich das „try and except“-Verfahren auch im Hauptprogramm anwenden, um das komplette Objekt „ego“ inkl. aller Attribute zu löschen (siehe Programm „micro_python-hallo_3-29.py):

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Nachdem wir nun wissen, was es mit den Konstrukten „__init__()“, „__del__()“ und „__str__()“ auf sich hat, wozu sich diese einsetzen lassen und auch wissen, dass sich mit dem „try and except“-Verfahren sehr einfach Fehlermeldungen nebst Programmausstiege abfangen lassen, machen wir uns ein weiteres Mal an die Arbeit und räumen das Hauptprogramm auf, indem wir den dortigen Programmkode in die Klasse „Fahrzeuge“ wie folg verlagern (siehe Programm „micro_python-hallo_3-30.py):

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

In diesem Zusammenhang wird nun das Objekt „ego“, d.h. der kleine Elektro-Stadtflitzer, in der Klasse „PKW“ instanziiert:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Bei dem obenstehenden Programmkode und der Instanziierung des Objektes „ego“ gilt es zu beachten, dass es sich bei der Übergabe der Variablen „a_beschleunigung“ und „a_dauer“ nicht um Attribute des Objektes handelt, sondern um Variablen der Klasse „Fahrzeuge“! Beim Objekt „ego“ gibt es derzeit nur ein einziges Attribut und zwar das der Geschwindigkeit „a_geschwindigkeit“ am Ende des Beschleunigungsvorgangs, d.h. am Ende des (Beschleunigungs-) Zeitfensters „a_dauer“.

 

Dass dem wirklich so ist, lässt sich zeigen, indem man sich die Variableninhalte im Hauptprogramm wie folgt mit dem

 

·       Statement print("Die Beschleunigung des 'ego' beträgt:", Fahrzeuge.a_beschleunigung, "m/s^2")

 

anzeigen lässt (siehe Programm „micro_python-hallo_3-31.py).

 

Im Gegensatz dazu lässt sich das Attribut „a_geschwindigkeit“ (= Variable „a_geschwindigkeit“ des Objektes „ego“ wie folgt mit dem

 

·       Statement print("Die Geschwindigkeit des 'ego' beträgt:", Fahrzeuge.ego.a_geschwindigkeit, "km/h\n")

 

anzeigen:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Dass wir nur über die übergeordnete Klasse „Fahrzeuge“ an die Variableninhalte der Klasse selbst als auch an die der Objekte in Form der Attribute ist dem Umstand der Objekt orientierten Programmierung (OOP) geschuldet, derzufolge die Klasse „Fahrzeuge“ eben die übergeordnete Klasse zu den Unterklassen „PKW“, „LKW“, „E-PKW“ oder „E-LKW“ usw ist.

 

Besonders interessant und wichtig ist der Umstand und die Erkenntnis, dass es mit dem Objekt „ego“ einen PKW der Klasse „PKW“ als Funktion der übergeordneten Klasse „Fahrzeuge“ gibt, der über ein Alleinstellungsmerkmal verfügt, das die anderen Objekte „vw“ und „bmw“ nicht haben: die beschleunigte Geschwindigkeit in Form des „ego“-Attributs „a_geschwindigkeit“.

 

Aber es gibt eben nicht nur das Alleinstellungsmerkmal in Form des „ego“-Attributs „a_geschwindigkeit“, sondern auch zwei „besondere“ Variablen „a_beschleunigung“ und „a_dauer“ der Klasse „Fahrzeuge“, die von den anderen Objekten „vw“ und „bmw“ nicht verwendet werden und demzufolge diesen auch nicht zur Verfügung stehen!

 

Es gibt also neben den beiden Attribute-Kategorien „statische“ und „dynamische Attribute“ der PKW-Klasse „vw“ und „bmw“ jetzt auch noch eine weitere Attribute-Kategorie „temporäre Attribute“ der PKW-Klasse „ego“, sozusagen mit Verfallsdatum! Dabei bezieht sich das (Verfalls-) Datum nicht auf ein zeitlich befristetes Datum wie z.B. jetzt, hier und heute um 20:55 Uhr am Mittwoch, den 04.12.2019, sondern vielmehr auf eine wie auch immer zeitlich befristete Existenz eines Attributes!

 

Programmiertechnisch lassen sich also jederzeit weitere PKW-Klassen wie z.B. die PKW-Klassen „opel“, „psa“ (Peugeot, Citroen), „renault“, „nissan“, „kia“ (Südkoreaner) usw. ohne existenzielles Verfallsdatum ins bestehende Programm aufnehmen, die programmiertechnisch nicht besonders sind.

 

Besonders sind hingegen Attribute mit existenziellem Verfallsdatum, wie z.B. das „ego“-Attribut „a_geschwindigkeit“, das programmiertechnisch durch die Konstrukte „__init()__“, „__str()__“ und „__del()__“ gekennzeichnet ist! -

 

Dabei dienen die beiden Konstrukte „__init()__“ und „__del()__“ ausschließlich dazu, neue, spezielle Variablen einer Klasse zu generieren, die dann wiederum nur dazu verwendet werden, um spezielle Attribute eines Objektes z.B. mit existenziellem Verfallsdatum zu definieren:

 

 

(Zum Vergrößern bitte auf das Bild klicken!)

 

Auch wenn die

 

·       Konstrukte „__init()__“, „__str()__“ und „__del()__“

nebst der

 

·       Konstruktköpfe „(self, a_beschleunigung, a_dauer)“ (siehe im obenstehenden Bild)

 

anfangs sehr kryptisch, da ungewohnt, aussehen, handelt es sich bei diesen doch um wichtige, programmiertechnisch gestalterische Möglichkeiten, um sozusagen nachträglich (Klassen-) Variablen zu generieren und dazu zu verwenden, um spezielle (Objekt-) Variablen in Form von Attributen z.B. mit existenziellem Verfallsdatum zu erzeugen! -

 

 

Wird demnächst fortgesetzt …

… deshalb diese Webseite als Lesezeichen/Favorit abspeichern!

 

 

 

[ Home ] [ Seitenanfang ]