Klassen importieren sich gegenseitig

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
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

Hallo

Ich habe für verschiedene Aufgaben verschiedene Klassen geschrieben. Oft benötige ich in einer Klasse zusätzliche Infos und importiere die Klasse aus einer anderen Datei, hier stoße ich jedoch auf Probleme, wenn sich die Parteien gegenseitig versuchen zu importieren. Wie kann ich dieses Problem umgehen?

Beispiel:
ich habe ein kleines Skript und importiere am Angang

Code: Alles auswählen

sys.path.append(os.path.join(os.path.expanduser('~'), 'MyTools'))
from Tools.Products.Products import Products
from Tools.Stock.Stock import Stock
from Tools.Stock.Locations.Locations import Locations
Gerade wollte ich der Klasse Locations eine neue Funktion hinzufügen, "get_locations_product_infos", daher wollte ich die Klasse "Products" importieren. Die Klasse Products importiert jedoch schon die Klasse Locations, um die Orte der Produkte zu finden.

Ich wüsste gerne wie ich das schöner lösen kann, Freue mich sehr auf Hinweise, Danke!
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

Ja, gibt es schon viele Themen dazu, z.B. viewtopic.php?t=19333
Mit hat nun geholfen, die Klasse erst kurz vor Bedarf zu importieren
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@martinjo: Was aber wenn ich mir die Importe anschaue der falsche Ansatz ist. Das sieht ja *sehr* nach einem Modul pro Klasse aus, was grundsätzlich schon mal komisch riecht, aber einfach mal falsch ist wenn Klassen so eng verbunden sind, dass die Module sich gegenseitig importieren. Dann gehören die offensichtlich ins selbe Modul oder die Funktionalität innerhalb der Klassen ist falsch aufgeteilt.

Edit: Selbst bei einem Modul pro Klasse ist da immer noch jeder Name einmal zu viel im voll qualifizierten Namen. WTF‽
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Ein Modul pro Klasse ist voll OK, schließlich haben wir ja alle mal Java gemacht. Auch fürs Repository und für Eclipse wird es so besser.
Die gegenseitige Abhängigkeit lässt sich oftmals durch ein Drittes Modul auflösen.
a fool with a tool is still a fool, www.magben.de, YouTube
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@MagBen: Ironie versteht nicht jeder.
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

Das hat wenig mit Ironie verstehen oder nicht zu tun wenn man eine Frage zu einem Fachgebiet beantwortet muss man davon ausgehen, dass die der Fragesteller nicht so gut mit der Materie auskennt und daher die Ironie in der Antwort logischerweise nicht verstehen kann.

Letztendlich sind alles Helferklassen für meine Warenwirtschaft, also Buchhaltung, Bank- und Paypal Transaktionen auflisten und zuweisen. Statistiken erstellen, VAT Nummern prüfen, Erinnerungs-Emails senden, Ware in Webshop und eBay abgleichen, Inventurlisten mit Bildern erstellen, Produktinfos aus dem Internet suchen, Forumeinträge generieren, DHL Label erstellen, Senungsnummern hinzufügen und Versandkosten errechnen um nur mal ein paar wenige zu nennen, alles ist irgendwie ineinander verzahnt, wenn ich das alles in eine Datei schreibe wird das etwas unübersichtlich und hätte über eine Millionen Zeilen Code.
Benutzeravatar
/me
User
Beiträge: 3554
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

martinjo hat geschrieben: Montag 17. Dezember 2018, 13:43 [...] alles ist irgendwie ineinander verzahnt [...]
Dann ist genau das dein Problem. Technisch gibt es Möglichkeiten, dass Klassen sich gegenseitig importieren. De facto spricht das aber in der weitaus größten Zahl der vorkommenden Fälle von einem falschen Anwendungsentwurf und daher sollte man erst einmal über die Struktur nachdenken.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@martinjo: die Auflistung Deiner Hilfsklassen hört sich auf den ersten Blick nicht sehr verzahnt an, das sind alles Aufgaben, die unabhängig voneinander laufen. Das meiste sind sogar Tätigkeiten, die gar keiner Klasse bedürfen (jedenfalls nicht direkt).
Kannst Du näher beschreiben, warum da was verzahnt ist?
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

martinjo hat geschrieben: Freitag 23. November 2018, 17:05 Gerade wollte ich der Klasse Locations eine neue Funktion hinzufügen, "get_locations_product_infos", daher wollte ich die Klasse "Products" importieren. Die Klasse Products importiert jedoch schon die Klasse Locations, um die Orte der Produkte zu finden.
Ich würde das eher so aufbauen: Ein Ort ist die Sammelstelle für verschiedene Produkte, also sollte auch er seine derzeit vorhandenen Produkte kennen. Ich nehme ja mal an, dass die Sache mit dem Ort eine dynamische Geschichte ist, sich also ändern kann, d. h. das Produkt kann den Ort wechseln. Und selbst wenn mit dem Ort nur genau ein Produkt verknüpft werden kann (z. B. weil er ein bestimmtes Fach im Lager darstellt), passt dieses Vorgehen immer noch.

Das Produkt hingegen sollte gar nichts davon wissen müssen, wo es gerade liegt. Da der Ort der "Verwalter" ist, muss er gefragt werden. Und somit muss das Produkt keine Orte mehr importieren, sondern es erfolgt stattdessen eine Zuweisung via location.set_product(dein_produkt) oder etwas in der Art. Diese Zuweisung macht aber nicht das products-Modul, sondern der Prozess, der zur Bewegung des Produktes führt, also z. B. der Warenein- oder ausgang oder eine Bewegung innerhalb des Lagers.

Das locations-Modul hätte außerdem eine Funktion zum Abfragen des Ortes für ein Produkt:

Code: Alles auswählen

def get_location(product):
    for location in locations:
        if location.has_product(product):
            return location
Und auch hier würde ich auf einen Import der Product-Klasse verzichten. Typprüfungen vermeidet man in Python bekanntlich so gut es geht. has_product() würde halt bei einem falschen Typen stumpf False liefern. Und schon ist man ein bißchen was von der Verzahnung beider Module losgeworden...
Antworten