Klasseninstanzen, die ihren eigenen Namen kennen

Zurück zur Übersicht


Nachdem man genauere Vorstellungen hat, wie Klasseninstanzen überhaupt miteinander reden, kann man das nun weiter verfolgen. Vorneweg, das nachfolgend Beschriebene ist natürlich, wie so oft, nicht der einzige Weg. Man kann das total umgehen und ganz anders machen. Aber es geht eben auch so, wie hier erläutert. Und dieser Weg hat eben auch seinen Reiz.

Wozu man das brauchen kann, wenn Klasseninstanzen ihren eigenen Variablennamen wissen?  Na so kann solch ein Objekt z.B. einen Eintrag mit seinem eigenen Namen in ein Dictionary vornehmen, so dass das Objekt nun in einem Team von Objekten eingereiht ist, die periodisch alle eine definierte Arbeit ausführen, indem eine Funktion das Dictionary durchmustert und sämtliche eingetragenen Objekte nacheinander mit ihrer jeweiligen work() - Funktion aufruft und die arbeiten dann brav. So etwas habe ich schon mal verwendet für ein Simulationsprogramm, in dem Knoten vernetzt waren und die alle nacheinander aufgerufen wurden und dabei verschiedenartige Funktionen ausgeführt haben. Waren alle einmal abgearbeitet, befand sich das Netz im Zustand n + 1. Und dann ging es wieder von vorn los. Wollte sich ein Objekt aus der Arbeitsschleife abmelden, hat es seinen Namen einfach aus der Teilnahmeliste (Dictionary) entfernt. Ist ja fast wie im richtigen Leben :-). Ebenso steht der Objektname auch für konkurrierende Objekte zur Verfügung. Wer kennt nicht die schönen Aquarien als Bildschirmschoner. Wird der kleine Fisch vom größeren gefressen (jeder Fisch ist eine eigene Instanz seiner Klasse), wird dessen Leben einfach vom großen Fisch ausgehaucht. Er killt das Objekt aus der Liste der lebenden Fische. Ein Generator, der z.B. die Gesamtzahl der existierenden Fische überwacht, erzeugt dann bald einen neuen Fisch derselben Art. der dann am linken Rand einfach neu auftaucht.
Ein anderes Beispiel wären Objekte, die in einem Wegenetz verbunden sind und die eine Wegesuche vollziehen sollen. Kennt der Knoten seinen eigenen Namen, dann kann er z.B. Wegevarianten verwerfen, die auf ihn selbst zurückkehren (also zirkular sind).

Und wie kann man dazu kommen? Ein kurzes vereinfachtes Beispiel ist bei den Erläuterungen zur exec - Anweisung angedeutet. Andere Varianten gehen auch ohne exec - Anweisung (die aus meiner Sicht recht unelegant wirkt). Eine davon verwendet die eingebaute Funktion apply(), eine andere Variante funktioniert so, dass sich die Instanzen bei der Initialisierung in ein globales Objekt (z.B. eine Liste) hinten eintragen und dabei aus der Länge der Liste ihre Positionsnummer in der Liste ermitteln.
Das sieht dann etwa so aus:

# Hierarchie von Einträgen

all = []
    # Das ist die globale Variable

class knoten:
    def __init__(self, text, vater):
        self.vor = vater
        self.text = text
        self.kind = []
        global all
        self.nr = len(all)
        all.append(self)
        # nicht die eigene Nummer wird eingetragen, sondern die Instanz selbst
    def zeige(self):
        global all
        if self.vor > -1:
            vatername = all[self.vor].text
        else:
            vatername = 'none'
        return str(self.nr) + '#' + self.text + ' mit Vater: ' + vatername
    def neukind(self, text):
        p = knoten(text, self.nr)
        self.kind.append(p)

k = knoten('root', -1)

eltern = ['vater', 'mutter']
    # hier drin steckt noch die Idee,  die Mehrfachvererbung anzuwenden
    # (hier: ein Objekt hat mehrere Eltern, was beim Löschen
    # auch mit zu beachten ist!
kinder = ['sohn', 'schwiegertochter']
enkel = ['enkel']

for i in eltern:
    p = knoten(i, 0)

all[1].neukind('michael')

for i in all:
    print i.zeige()
 



Einschub für Fortgeschrittene:

In den klassischen Programmiersprachen wäre ein vergleichbarer Lösungsansatz ein Array mit Zeigern gewesen, die auf die jeweiligen work() - Funktionen gezeigt hätten. Mit Aufrufen dieser Funktionsadressen wären die Funktionen dann ausgeführt worden. Das ließ sich aber nicht mit wenigen Zeilen programmieren!

Es gibt auch noch eine Vorgehensweise, in der sich die Objekte nicht gegenseitig mit ihren Namen aufrufen. Das wird dann so gelöst, dass die ganze Struktur (Hirarchie oder Vernetzung) in einer passiven Variablen gehalten wird (z.B. Dictionary oder verschachtelte Listen) und ein "Überobjekt" in dieser Datenstruktur navigiert. Das heißt es wird anstelle der o.g. Namen von Objekten jetzt mit Positionsnummern in der Liste oder mit Keys des Dictionarys gearbeitet. Dann erkennt das Navigationsobjekt abhängig von seiner Stellung in der Datenstruktur die jeweiligen Möglichkeiten, in die nächste Postion zu wechseln.