Wechselseitiger import

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mechanicalStore
User
Beiträge: 174
Registriert: Dienstag 29. Dezember 2009, 00:09

Folgendes Beispiel funktioniert, aber ist das legitim, oder einfach nur "Sch..." Design?

Ich habe tatsaechlich einen Fall, wo ich wechselseitig auf die jeweils andere Klasse zufgreifen will. Klar kann ich ein drittes File erstellen und da beides importieren, aber dann waere die Funktionalitaet nicht mehr in den methoden der Klassen, sondern quasi aussen vor. Wie gehe ich also sinnvollerweise vor?

Code: Alles auswählen

# file a.py
from b import *

class A:
    def __init__(self):
        self.s: str = 'abc'

def main():
    y = B()
    y.test()

if __name__ == '__main__':
    main()

Code: Alles auswählen

# file b.py
from a import *

class B:
    def __init__(self):
        self.t: str = 'def'

    def test(self):
        x = A()
        x.s = f'{self.t}  123456'
        print(x.s)
Benutzeravatar
sparrow
User
Beiträge: 4529
Registriert: Freitag 17. April 2009, 10:28

Erst einmal geht man so vor, dass man keine *-Importe verwendet.
Damit holt man sich unkontrolliert Namen in den Namensraum - und das möchte man nie.
Und dann funktioniert dein Code auch nicht mehr, wenn man explizit importiert.

Wenn Klassen so sehr voneinander abhängen gehören sie mMn in ein Modul.
Es ist wenig sinnvoll für jede Klasse ein Modul anzulegen.
Wobei sie das ja in deinem Beispiel gar nicht tun. Sondern die Aufteilung, wie du sie zeigst, ist schlicht schlecht bis falsch. Die Klassen hängen nicht voneinander ab.
Zuletzt geändert von sparrow am Dienstag 17. Juni 2025, 16:59, insgesamt 1-mal geändert.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1224
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

# file main.py

Code: Alles auswählen

from base import B


def main():
    y = B()
    y.test()


if __name__ == '__main__':
    main()

# file base.py

Code: Alles auswählen

class A:
    def __init__(self):
        self.s: str = 'abc'

class B:
    def __init__(self):
        self.t: str = 'def'

    def test(self):
        x = A()
        x.s = f'{self.t}  123456'
        print(x.s)
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
__blackjack__
User
Beiträge: 14005
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Noch eine Anmerkung zu Typannotationen: Sowohl menschliche Leser als auch Prüfwerkzeuge sind schlau genug den Typ einer literalen Zeichenkette zu erkennen. Da muss man bei der Zuweisung der Zeichenkette nicht noch mal hin schreiben, dass das eine Zeichenkette ist.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
mechanicalStore
User
Beiträge: 174
Registriert: Dienstag 29. Dezember 2009, 00:09

Da das Beispiel hier nicht gut ankam (mir sind die monierten Dinge bewusst, es war nur ein grobes Beispiel. Aber auch mit so einer Aussage komme ich hier nicht durch, das weiß ich.), bleibe ich mal ganz konzeptionell (ich kann auch keinen Code zeigen, da das im Moment nur theoretische Überlegungen sind)

Code: Alles auswählen

Class Kategorie_Element
Class Partition_A
Class Partition_B

Class Basis:
    More_Data = …
    Kategorie_Elemente = []
    Partitionen_A = []
    Partitionen_B = []

Basis_Liste = Basis.create(…..Basis-Objekte….
Es gibt eine Objekt-Liste der Klasse Kategorie_Element aus einer beliebigen Datenquelle. Diese haben verschiedene Kategorien. Je nach Kategorie wird je ein Basis Objekt erzeugt und die entsprechende Teilmenge der Kategorie_Elemente in dessen entsprechende Listen-Instanz einsortiert. Das Basis-Objekt erhält außerdem noch einige Meta-Daten (MoraData).

Im zweiten Step werden nun je Basis_Element die Kategorie_Elemente durchlaufen und nochmal zerteilt in Partitionen. Wobei die Anzahl der erzeugten Objekte von Partition_A und Partition_B unterschiedlich sein kann (B kann mehrfach einem A zugeordnet sein). Um nun ein Partition_A Objekt zu bauen, muss die Liste der Partition_B nach Informationen durchlaufen werden. Partition_A braucht Daten von durchsuchten Objekten in Partition_B und Vice Versa. Außerdem brauchen beide Partitionen auch noch Daten aus der Basis Class (More_Data).

Man soll ja Objekte so bauen, dass sie nach Erzeugen Gebrauchsfertig sind, was aber im Falle von Class Basis in dem Fall schier unmöglich ist. Ebenso müssen die Listen Partition_A und Partition_B simultan aufgebaut werden, da ansonsten die Zuordnungen fehlen, bzw. Später nicht mehr auffindbar sind. Eigentlich soll man aber auch Listen Gebrauchsfertig bauen und ordentlich zurück geben. Auch das ist so nicht möglich. Und zuguterletzt werden ja den Objekten der Basis Class erst im zweiten Step die Daten der Partitionen quasi „injiziert“, sodass sie erst dann gebrauchsfertig sind.

Ein letzter Versuch der Frage, Was ist also sinnvoll?
Sirius3
User
Beiträge: 18253
Registriert: Sonntag 21. Oktober 2012, 17:20

Für theoretische Überlegungen sind Deine Beschreibungen schon sehr detailiert.
Da Du aber sehr kryptisch bleibst, kann ich mir darunter nichts vorstellen. Lass mal all die Einordnung in Klassen weg und versuche nur zu beschreiben, welches konkrete Problem Du lösen willst.
Dass man eine Liste an Objekten hat, ist üblich, dass man diese Liste dann aufteilt auch.
Dass aber ein Objekt auf eine Basis zugreifen muß und umgekehrt, ist eher ein Designfehler.
Denke eher an Funktionen, die Daten verarbeiten und frage Dich, welche Daten diese brauchen, dann ergibt sich normalerweise ganz natürlich ein Hierarchie.
Antworten