__blackjack__ hat geschrieben: ↑Freitag 16. Dezember 2022, 17:40
@Holzbein: SQL als Zeichenketten basteln klingt dann schon nach der nächste „Alarmglocke“. Das macht man eigentlich auch nicht, für so etwas gibt es beispielsweise SQLAlchemy. Da würde ich an Deiner Stelle mal schauen ob Du das nicht gerade selbst irgendwie nachprogrammierst, was es dort schon fertig gibt.
Danke für den Hinweis. Es gibt sicher 100erte Klassen, die mir das Leben erleichtern würden. Nur kennen sollte man die. - Ich schau mir das gerne an.
Edit: habe mir jetzt Alchemy angeschaut. Auf den ersten Blick nur ein Wrapper für SQL. Da ist für mich jetzt kein großer Unterschied ob ich SQL Strings zusammenbau oder mit 'add_all' hinzufüge und die Objekte vorher zusammenstelle. Die Unabhängikeit von der DBengine im Hintergrund ist natürlich verlockend. Werde das weiter verfolgen.
__blackjack__ hat geschrieben: ↑Freitag 16. Dezember 2022, 17:40
Was meinst Du mit Arrays? Du hast da keine gezeigt, es gibt in Python aber tatsächlich Arrays — damit sind in der Regel Numpy-Arrays gemeint.
Sorry - für mich sind Array alles, was in einem Datenbaum strukturierte Daten speichert. Ob die Dict wie in Python oder anders heißen.....
__blackjack__ hat geschrieben: ↑Freitag 16. Dezember 2022, 17:40
Die Organisationseinheit für Funktionen ist das Modul, nicht die Klasse.
Das war schon ein sehr guter Hinweis. Kommt mir und meiner Arbeitsweise näher. Habe ich , vor dieser Diskussion hier, nicht gekannt.
__blackjack__ hat geschrieben: ↑Freitag 16. Dezember 2022, 17:40
„Problemdomäne“ ist kein Python-spezifischer Begriff. Das ist die Begriffswelt von dem Problem das gelöst werden soll, da kann der Begriff „Klasse“ ja auch eine Bedeutung haben. Also beispielsweise wenn man Fahrzeuge modelliert, beispielsweise Schiffe, dann kann es dort Schiffsklassen geben, die nichts mit der Klasse in der Programmierung zu tun hat. So könnte es auch eine Sensorklasse geben in der realen Welt. Dann kann man `class` in einem Namen dafür im Programm verwenden. Wenn der Wert dort nichts mit einer Sensorklasse in der realen Welt zu tun hat, dann ist er falsch, denn programmtechnisch ist das ja keine Klasse was dort an den Namen gebunden wird.
OK
__blackjack__ hat geschrieben: ↑Freitag 16. Dezember 2022, 17:40
Um Klassen zu verwenden muss man nicht zwingend objektorientiert denken, denn das ist in Python halt auch der Verbunddatentyp. Also da wo man in anderen Programmiersprachen ``struct``, TYPE, RECORD, oder Ähnliches verwendet um einen Satz an Daten zu beschreiben und zusammenzufassen und als *einen* Wert ansprechen zu können, verwendet man in Python auch schon eine Klasse. Das sind in den älteren Sprachen in der Regel auch die Sprachkonstrukte, die zu Objekten/Klassen weiterentwickelt wurden. Python hat diesen Zwischenschritt einfach ausgelassen, weil es nicht gross Sinn macht neben der Klasse, die das ja mit abdecken kann, extra noch etwas anderes einzuführen. (Oder man könnte das zumindest denken, denn Java 14 führt ``record``-Klassen ein.)
Das wird mein Problem mit Python sein. Und da muss ich erst umdenken lernen.
__blackjack__ hat geschrieben: ↑Freitag 16. Dezember 2022, 17:40
Die Kombination meinte ich und die erste Zeile braucht es dort nicht, die hat keinerlei Auswirkung als einfach ein bisschen Rechenzeit und kurz Speicher zu verbrauchen, denn das `defaultdict`-Objekt wird erzeugt und gleich in der nächsten Zeile ja wieder verworfen ohne das irgend etwas damit gemacht worden wäre.
Also, bei mir läuft das ohne dieser Zeile nicht
__blackjack__ hat geschrieben: ↑Freitag 16. Dezember 2022, 17:40
Und mir ging es ja gerade nicht um das herein*holen* sondern das die `__init__()` bereits die richtigen Daten übergeben bekommt, statt sich die aus einer übergeordneten Struktur selbst heraus zu holen. Für Tests muss man hier ja eine Datenstruktur erstellen die nur aus einem Schlüssel-/Wert-Paar besteht und die nur existiert damit sich die Methode diesen einen Wert da heraus holen kann.
Und genau das war das Ursprungsproblem - Ursprungsfrage.
Ich übergebe in __init__ Daten. Wenn 'außen' dann Werte geändert werden, erscheinen die jedoch nur teilweise in der Klasse geändert.
Ich habe auch nur Teil-Daten-Strukturen übergeben. Eben den Teil, den die Klasse und ihre Methoden (oder was ich dafür gehalten habe) braucht.
__blackjack__ hat geschrieben: ↑Freitag 16. Dezember 2022, 17:40
Bei solchen Wrapperklassen um Einzelwerte ist immer die Frage ob und welchen Mehrwert die bieten. Das kann Vorteile bieten wenn es den Code lesbarer macht und/oder Polymorphie möglich macht, aber wenn es am Ende einfach nur die Schreibweise ``data.do_something()`` vs. ``do_something(data)`` ist, finde ich das nicht genug um eine Klasse mit einem Attribut zu rechtfertigen.
Mit dem Hinweis auf Module sehe ich das genauso.
__blackjack__ hat geschrieben: ↑Freitag 16. Dezember 2022, 17:40
Und „das meisste“ sollte nicht in `__init__()` passieren. Das sollte in aller Regel eher so wenig wie möglich passieren. Meistens nur Zuweisung der Attribute. Validierung und einfache Konvertierungen kann da noch dazu kommen. Alles was komplexer ist, sollte dort nicht stehen, sonst leidet schnell die Testbarkeit der Objekte, weil man dann nicht mehr so einfach Objekte in einem bestimmten Zustand erstellen kann. Wenn komplexere Schritte nötig sind um die Werte für den Zustand vorzubereiten, würde ich das in Klassenmethoden unterbringen.
Bei meinem (großen) Programm, ist das so. In __init__ nur Datenübergabe, Zuordnung von Teilstrukturen in Variablen mit klingenden Namen. Bearbeitung natürlich in den Methoden.
__blackjack__ hat geschrieben: ↑Freitag 16. Dezember 2022, 17:40
``include`` in PHP macht etwas anderes. Das fügt ja quasi an der Stelle den Inhalt der anderen Datei ein. In Python wird jedes Modul genau einmal geladen und ausgeführt, egal wie oft ``import`` mit diesem Modulnamen irgendwo ausgeführt wird. Beim ersten ``import`` passiert das, und bei jedem weiteren ``import`` wird einfach nur das bereits existierende Modul verwendet. Und das hat einen eigenen Namensraum.
Hast recht, nicht ganz das Gleiche.
grubenfox hat geschrieben: ↑Samstag 17. Dezember 2022, 00:04
Bin jetzt nicht sicher ob 'Messwert' und 'SensorAnsteuerung' als Klasse sich hier als sinnvoll erweisen, aber jedenfalls haben wir Sensoren und irgendwelche Auswertungen... welche Daten und welches Verhalten dann in diese Klassen müsste, wäre dann zu klären.
Danke. für den Versuch. Wollte aber nicht, das jemand sich mit dem großen Programm herumplagt.
Aber vielleicht kurz zur Erklärung.
Ich bekomme via MQTT Sensorendaten. Als Floatwerte, Integerwerte, Stringwerte. Je nach angeschlossenem Sensor.
Manche Werte müssen auch via Modbus gepollt werden.
Stringwerte müssen erst über eine Translatetabelle umgesetzt werden, damit ALLES als float. Macht so im ersten Moment wenig Sinn, ist aber für das einfache DBhandling dann gut.
Kommt ein neuer Sensorwert hinzu, werden auch von passenden Methoden/Funktionen die DB-Tabellen erweitert. Ob und wie steht wieder, zum Sensorwert passend, in dieser 'ominösen' Datenstruktur.
Diese Werte werden gesammelt. Es gibt 4 Zeiträume für die Charts. 2h, 12h, 2Tage, 7Tage.
Bei manchen Werten benötige ich Min- Maximalwerte innerhalb des Zeitraumes, bei anderen ist es einfach der (zeitlich zufällige) Momentanwert, manchmal Mittelwerte.
Bei manchen Werten müssen Faktoren den Wert erst bewerten.
Dann kommen Funktionen dazu, die z.b. in einem Zeitraum Oktober - März und passender Urzeit basierend auf verschiedenen Sensorwerten (Temperaturen) Heizkreise ein- und ausschaltet. Oder, wenn Grenztemperaturen erreicht werden, werden andere Pumpen, Ventile geschaltet .....
Gesendet dann via MQTT oder Modbus oder teilweise anderen Protokollen. Oder auch direkt via GPIOs am RaspPi.
Das alles via Nodered bedienbar. Und mit Charts (JavaScript), die aus einer DB die zeitlich und Wertmäßig aufbereiteten fertige Daten nehmen.
Diese DB muss passend gefüllt werden.
Also auch ein SQL Teil, welcher die richtigen Werte zusammen sucht und in DB einlagert. Welche Werte das sind ist wieder für jeden Wert, eben in dieser, meinen "ominösen" Datenstruktur definiert.
Und es wird ein SQL String generiert, welcher als String auf einen Webserver überspielt wird, damit dort das PHP Programm die Werte wiederum in ein DB einlagert, um auch außerhalb des Heimnetzes Werte und Bedienungen zu haben.
Ach ja, natürlich müssen die Bedienungen von der Webseite auch gepollt werden, um im Heimnetz zu wirken.
Ich mach deshalb diese "ominösen" Datenstruktur. Dort stehen meine Sensor Daten drinnen, passend auch, wie das Rohdatum behandelt werden soll, die Max- Min- Mittelwerte zum Datum passend.
Kommt nun ein Sensor dazu, ergänze ich die Datenstruktur um diesen Sensor. Da ist dann mit 3-5 Zeilen ALLES definiert, was mit dem Wert passieren muss, damit die einzelnen 'Funktionen' damit arbeiten können / dürfen.
Und kommt eine neu Funktionalität zum Programm hinzu : Neue/weiter Klasse/Methode, einbindung im Mainprogramm, eventuell Parameterergänzung in Datenstruktur und fertig.
Für mich hatte das nach Klassen geklungen, die 'nur' ihren Teil machen und ein Ergebnis 'ausspucken', das dann wiederum eventuell in die 'Datenstruktur' eingelagert wird.
Damit hätte ich den Vorteil, das die Bearbeitungsfunktion nur in der Klasse (oder Funktion) zu betrachten ist, Sensoreigenschaften nur in der Datenstruktur usw.
Und eigentlich funktioniert mein Konzept auch sehr gut. Änderungen sind extrem einfach zu machen.
Bis ich über das Orginalproblem stolperte, dass in gewissen Fällen in diesem Dict geänderte Daten dann in den Klassen/Methoden nicht geändert erscheinen.
Aber das lässt sich mit Funktionen in Modulen mit Parameterübergabe lösen.
(Das einfachste wäre Übergabe als reference, dann könnte die Datenstruktur direkt geändert werden, aber das spielts in Python nicht.
)
Aber ich wollte euch da eigentlich nicht mit dem großen Projekt zuquatschen.
Danke für euer Mitdenken.
D