Seite 1 von 1

Python variablen mit den Wert einer Instanz einer Klasse zurückverfolgen

Verfasst: Dienstag 22. Juni 2021, 11:54
von MupfSpace
Hallo,

Ich habe eine Instanz einer Klasse.
Diese Instanz teile ich mehreren variablen in verschiedenen Klassen zu, diese Klassen instanziiere ich dann auch.

Code: Alles auswählen

foo = Foo()

class A:
    def __init__(self):
        self.a_foo = Foo()
		
class B:
    def __init__(self):
        self.b_foo = Foo()
		
a  = A()
b = B()


nun möchte ich, in der Foo Klasse eine Funktion haben, mit der ich alle Klassen und Instanzen der jeweiligen Foo-Instanz, und den Namen diese Variablen abfragen kann.
also...:

Code: Alles auswählen

class Foo:
    def get_locations(self):
        ...
		
foo = Foo()

... # siehe oben

print(foo.get_locations)

# erwartete Ausgabe: [("a_foo", <__main__.A object at ...>, <class '__main__.A'>), ("b_foo", <__main__.B object at ...>, <class '__main__.B'>)]
wie kann ich das realisieren?

Re: Python variablen mit den Wert einer Instanz einer Klasse zurückverfolgen

Verfasst: Dienstag 22. Juni 2021, 12:11
von __deets__
Ein Weg besteht in einer (globalen!) klassenvariable auf Foo, die alle Instanzen nachverfolgt, weil die sich darin selbst registrieren. Den Namen wiederum bekommt du NICHT. Das ist ganz theoretisch machbar, aber dann wird es wenig robust und hässlich.

Grundsätzlich ist so ein Vorgehen aber erstmal ungewöhnlich, und sollte wegen der globalen Variable vermieden werden. Welches Problem willst du mit diesem Vorgehen lösen?

Re: Python variablen mit den Wert einer Instanz einer Klasse zurückverfolgen

Verfasst: Dienstag 22. Juni 2021, 12:28
von MupfSpace
Ich möchte eine Property klasse schreiben, der ein wert zu gewiesen werden kann und die sich wie eine normale variable verhält (wie das funktioniert weiß ich, also __set__, __get__, __add__, ...).
Dann möchte ich, wenn sich der Wert verändert, mit isinstance überprüfen ob die Property in einer bestimmten Klasse ist (z.B. ein Widget), die ich selber geschrieben habe und die eine update Funktion enthält, diese update Funktion aufrufen und der Name der Variable soll übergeben werden um festzulegen was genau upgedated werden soll...

Re: Python variablen mit den Wert einer Instanz einer Klasse zurückverfolg

Verfasst: Dienstag 22. Juni 2021, 12:44
von __deets__
Das ist aber sehr weit weg von der ursprünglichen Frage. Weder kommen da jetzt alle Instanzen vor, noch war vom descriptor protocol die Rede.

Mit dem geht seit Python 3.4 oder so auch, dass man den Namen eines Properties bekommt, __set_name__ oder so. Musst du mal nachlesen.

Re: Python variablen mit den Wert einer Instanz einer Klasse zurückverfolgen

Verfasst: Dienstag 22. Juni 2021, 13:06
von MupfSpace
Nein das mit dem set sachen ist für die Frage egal, da weiß ich wie das geht.
Ich muss auf die Instanzen und die Namen zugreifen, um eben beim Aufruf von z.B. __set__ zu überprüfen, ob die Position/Instanz eine Instanz von meiner Klasse ist, um dort eine update/rerender Funktion aufzurufen.

Re: Python variablen mit den Wert einer Instanz einer Klasse zurückverfolgen

Verfasst: Dienstag 22. Juni 2021, 13:27
von __deets__
Ich glaube du hast meine Antwort nicht verstanden. Ich rede nicht von __set__.

Re: Python variablen mit den Wert einer Instanz einer Klasse zurückverfolgen

Verfasst: Dienstag 22. Juni 2021, 13:49
von DasIch
Hier ist ein Beispiel dafür was __deets__ gemeint hat:

Code: Alles auswählen

class MyClass:
    def update(self, name, value):
        print("update", name, value)


class TheirClass:
    pass


class MyDescriptor:
    def __init__(self):
        self.name = None

    def __set_name__(self, owner, name):
        self.name = name

    def __set__(self, instance, value):
        if isinstance(instance, MyClass):
            # Safety: name is not None because it's guaranteed that __set_name__
            # is called with a name when the class `instance` is an instance
            # of is created.
            instance.update(self.name, value)
        else:
            print(f"Warning: cannot update {instance!r} not a subclass of MyClass")


class A(MyClass):
    foo = MyDescriptor()


class B(TheirClass):
    bar = MyDescriptor()


def main():
    a = A()
    a.foo = 1

    b = B()
    b.bar = 2


if __name__ == "__main__":
    main()
Die Alternative wäre über den Garbage Collector sich die Referenzen anzuschauen aber dass ist sehr ineffizient und nicht sinnvoll außer für Spielereien oder Debugging.