Seite 1 von 1

Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 13:17
von hcshm
Um die Instanzen einer Klasse zu erfassen, habe ich das nachfolgende Script erstellt.
Leider finde ich nicht den Fehler, der zu folgender Meldung führt:
AttributeError: 'Kind' object has no attribute '_instances'
Könntet Ihr mir bitte helfen?

import datetime
import weakref

_instances = set()

class Kind:

def __init__(self, varname, vorname, nachname, geburtstag):
self.varname = varname
self.vorname = vorname
self.nachname = nachname
self.geburtstag = geburtstag
self._instances.add(weakref.ref(self))

def alter(self):
today = datetime.date.today()
alter = today.year - self.geburtstag.year
if today < datetime.date(today.year, self.geburtstag.month, self.geburtstag.day):
alter -= 1
return alter

@classmethod
def getinstances(cls):
x = set()
for ref in cls._instances:
obj = ref()
if obj is not None:
yield obj
else:
x.add(ref)
cls._instances -= x

janpeter = Kind(
'janpeter',
'Jan-Peter',
'Schneider',
datetime.date(1981, 10, 28)
)
katrin = Kind(
'katrin',
'Katrin',
'Schneider',
datetime.date(1983, 9, 16)
)
robert = Kind(
'robert',
'Robert',
'Schneider',
datetime.date(1986, 4, 28)
)
stefan = Kind(
'stefan',
'Stefan',
'Schneider',
datetime.date(1995, 3, 7)
)
for obj in Kind.getinstances():
print(obj.varname)

Re: Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 13:24
von Sirius3
Was ist ein Varname? Warum willst Du überhaupt alle Instanzen wissen? Entweder Du hast eine Liste mit Instanzen, die Du für einen bestimmten Zweck brauchst, oder nicht. Bei Dir also alle Kinder in eine Liste packen und gut ist.
_instances sollte ein Klassenattribut sein und vom Typ WeakSet. getinstances ist dann überflüssig.

Re: Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 13:28
von hcshm
Vielen Dank für die prompte Antwort. Ich hätte gern alle Instanzen im nachhinein abgegriffen, auch wenn sie mal ergänzt werden, um dann über das vollständige Set iterieren zu können, auch wenn es mal mehr werden (was nicht für Kinder gilt, das ist nur ein Übungsbeispiel)

Re: Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 14:05
von Sirius3
Außer für Spielereien ist das aber nie sinnvoll oder gut. Was soll denn dreh Anwendungsfall sein?

Re: Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 16:36
von hcshm
Eine vollständige Auflistung aller Instanzen soll letztendlich genau das absichern, was Du als Voraussetzung beschrieben hast: Die prinzipiell vorher - aber nicht immer - vorhandene (vollständige) Liste. Es geht mir um die Frage: Habe ich aller meiner Kontakte als Instanzen erfasst? Und wenn nicht: wer fehlt?

Re: Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 16:39
von sparrow
Dann solltest du sie auf jeden Fall in eine Liste tun. Aber die Liste hat nichts in der Klasse zu suchen.

Re: Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 16:41
von hcshm
Ich will die Liste nicht in die Klasse bringen, ich will sie aus der Klasse generieren.

Re: Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 16:50
von sparrow
Du versuchst die ganz offensichtlich mit _instances in die Klasse zu bringen. Und die gehört da nicht hin.
Eine Klasse bildet ein Objekt ab. Die Liste musst du da führen, wo die Instanzen erstellt werden, bzw. dort wo sie "aufgehoben" werden müssen. Das ist nicht in der Klasse. Das Design ist kaputt.

Re: Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 16:59
von hcshm
Kaputt hin oder her: Meine Kontakte habe ich in verschiedenen Listen - teilweise auf Papier. Und zukünftig habe ich sie als Instanzen. Und jetzt möchte ich sicher sein, dass ich alle Kontakte instantiiert habe. Und dafür brauche ich eine Zusammenstellung aller Instanzen. Damit ich anschließend in meinen Ursprungs-Kontaktlisten aushaken kann.

Re: Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 17:04
von kbr
Das geht, ist aber selten eine gute Idee:

Code: Alles auswählen

class Test:
    instances = list()
    def __init__(self):
        self.__class__.instances.append(self)
    def __repr__(self):
        return 'id: {}'.format(id(self))

tests = [Test() for _ in range(5)]
del tests

for item in Test.instances:
    print(item)    
Wie Du siehst, kann nun der Garbage Collector nicht mehr greifen und Du erzeugst potentielle Speicherlecks. Besser ist es, Instanzen außerhalb der eigenen Klasse zu verwalten. Das macht auch den Code besser verständlich:

Code: Alles auswählen

class Test:
    def __repr__(self):
        return 'id: {}'.format(id(self))

tests = [Test() for _ in range(5)]

for item in tests:
    print(item)    
In tests sind auch hier alle Deine Instanzen, die Du dann auf Papier abhaken kannst.

Re: Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 17:04
von sparrow
Wo ist denn jetzt dein Problem die Instanzen in eine Liste zu packen?
Ich verstehe deine Sorgen nicht.
Ob du die nun auf Papier oder auf Steintafeln hast ist doch völlig egal für die Lösung.

Spätestens wenn du die speichern willst, musst du sie ja auch wieder laden. Und dort wo du sie lädst, packst du sie halt in eine Liste.

Code: Alles auswählen

import datetime

class Kind:

    def __init__(self, varname, vorname, nachname, geburtstag):
        self.varname = varname
        self.vorname = vorname
        self.nachname = nachname
        self.geburtstag = geburtstag

    def alter(self):
        today = datetime.date.today()
        alter = today.year - self.geburtstag.year
        if today < datetime.date(today.year, self.geburtstag.month, self.geburtstag.day):
            alter -= 1
        return alter


def main():
    kinder = []
    kinder.append(Kind('janpeter','Jan-Peter','Schneider',
                        datetime.date(1981, 10, 28)))
    kinder.append(Kind('katrin','Katrin','Schneider',
                        datetime.date(1983, 9, 16)))
    kinder.append(Kind('stefan','Stefan','Schneider',
                        datetime.date(1995, 3, 7)))
    kinder.append(Kind('stefan','Stefan','Schneider',
                        datetime.date(1995, 3, 7)))
    for kind in kinder:
        print(kind.vorname)
    

if __name__ == "__main__":
    main()

Re: Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 17:17
von Sirius3
Ich verstehe nicht, wo die Kontakte denn an unterschiedlichen Stellen erzeugt werden sollen? Im Programmcode gibt es meist nur eine Stelle, an der etwas generiert wird, egal aus was. DAAD mit den Abgleich verstehe ich auch nicht. Mit was willst du denn vergleichen.
Ich habe die Befürchtung, Du verwechselst ein Programm mit einem Notizzettel, wo ungeordnet was notiert wird. Kannst Du genauer beschrieben, was Du vorhast?

@kbr: deshalb verwendet der OP ja weakref.

Re: Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 17:39
von kbr
Sirius3 hat geschrieben: Sonntag 8. März 2020, 17:17 @kbr: deshalb verwendet der OP ja weakref.
Ja, stimmt. Was zwar Speicherlecks entgegenwirkt, aber die weakref-Instanzen aller gelöschten Objekte weiter mitschleppt. So etwas ist aus meiner Sicht zumeist ein Designfehler.

Re: Instanzen einer Klasse erfassen / auflisten

Verfasst: Sonntag 8. März 2020, 20:19
von hcshm
Vielen Dank, vor allem auch für die Erläuterungen warum/weshalb!