Umsteigerfrage zu List, Dictionary o.ä.

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
Papageno
User
Beiträge: 33
Registriert: Sonntag 21. Dezember 2014, 10:53

In VB6 gibt den Datentyp Type, welcher aus mehreren unterschiedlichen Datentypen eine Art Recordset bildet. Dieses lässt sich in ein Array verwandeln und die einzelnen "Felder" über array(index).Feld1, array(index).Feld2, ... befüllen, etc. Der Vorteil ist, dass man klare Namen für ein sonst krytisches 2 dimensionales Array hat.

Wie stelle ich das in Python 3.4 dar? List ist mir zu sequentiell, Dictionary scheint mir gar nicht geeignet. Ist vielleicht eine im Speicher abgelegte sqlite DB das beste Mittel? :K

Wie löst ihr sowas?
BlackJack

@Papageno: Entweder eine Liste in der Wörterbücher als Elemente gespeichert werden oder statt Wörterbücher ein selbst geschriebener Datentyp, also eine Klasse.

Wobei das Muster das Du da beschreibst absolut nicht zu Python passt. Also dieses anlegen eines ”Arrays” mit ”leeren” Elementen um dann mit einer Indexschleife die Attribute der einzelnen Elemente mit Werten zu versorgen. In Python ist die Liste *der* sequentielle Datentyp und die erstellt man in dem man sie nach und nach mit Elementen füllt. Dazu braucht man keinen Index. Und das zuweisen an die Attribute ”von aussen” braucht man im einfachen Fall auch nicht, weil man diese Werte normalerweise der `__init__()` übergibt, beziehungsweise sie an diese Methode übergeben werden und die Zuweisung dann dort passiert, also dann wenn man die Objekte erstellt die an die Liste angehängt werden. An der Stelle sei auch die „list comprehension”-Syntax zum erstellen von gefüllten Listen erwähnt.
Papageno
User
Beiträge: 33
Registriert: Sonntag 21. Dezember 2014, 10:53

@BlackJack:
Thx, aber irgendwie peile ich das noch nicht so ganz. Mir erscheint das für Python ziehmlich unstrukturiert. So wie ich dich verstehe nehme ich eine Liste, welche ich in einer Schleife mit Liste.append(InFunktionermittelterWert) befülle. Nun mache ich 5 Werte die alle zum selben "Datensatz" (Index) gehören. Das heist beim Auslesen die Werte Liste.(Index +1), Liste.(Index +2)... wieder zusammenzusetzen. Kann ein einzelner Wert (noch) nicht ermittelt werden, muss er zunächst mit (0) befüllt werden und später dann mit Liste.insert(index,Wert) korrigiert werden. Geht das nicht einfacher?
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Papageno: BlackJack hat doch genau das Gegenteil gesagt. Man füllt kein mit Füllwerten, um sie später durch die richtigen Werte zu ersetzen, sondern erzeugt dann, wenn man die Werte hat, ein Dictionary, eine Klasseninstanz oder ein Tuple und hängt es an die bestehende Liste an. Expliziten Index-Zugriff braucht man so gut wie nie.
Papageno
User
Beiträge: 33
Registriert: Sonntag 21. Dezember 2014, 10:53

@Sirius3: Das habe ich schon verstanden. Ich steh grad nur auf dem Schlauch, weil mir irgendwie die explizite Zuweisung wie in einem Dictionary fehlt. Was ich machen möchte ist mit einer Tabelle vergleichbar in der die Zeilen die Zeitangabe bestimmen und die Spalten die Werte enthalten, so dass ich später über eine bestimmte Spalte iterieren und nach Zeitangabe sortieren kann. (Ich glaub so heists :? )
BlackJack

@Papageno: Kannst Du mal ein konkreteres Beispiel geben? Denn ich glaube wir reden hier irgendwie aneinander vorbei.
Papageno
User
Beiträge: 33
Registriert: Sonntag 21. Dezember 2014, 10:53

@BlackJack
Ich schreib dir mal den Basic Syntax, ich glaube du weise sofort was ich meine:

Code: Alles auswählen

Type Rating
    PositionID As Long
    Eigenschaft As String
    DeltaT As Double
    DeltaE As Double
    Bewertung As Integer
    Kommentar As String
End Type

Dim aRating() As Rating
Und das jetzt in Phyton :roll:
BlackJack

@Papageno: Das reicht nicht so ganz denn die Klasse dazu sieht sehr langweilig aus und eine leere Liste zu erzeugen kannst Du sicher auch ohne Beispiel. Man bräuchte mal Code oder zumindest eine Beschreibung was damit nun gemacht werden soll.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Na wenn du Records suchst, dann sind Klassen eine Loesung (oder eben Dictionaries, wenn es unstrukturierter sein darf) oder eben `namedtuple`, wenn die Records unveraenderlich sein sollen (was aber deine bisherigen Beschreibung widerspricht).
Papageno
User
Beiträge: 33
Registriert: Sonntag 21. Dezember 2014, 10:53

@BlackJack: gecodet hab ich noch nix, klebe noch an der Theorie. Werde aber ein Beispiel nachreichen. Vermutlich Ende der Woche.
@cofi: Die Antwort ist Klasse, im Sinne von Klassenkonstruktion. Kann man Klassen in Listen verwenden?
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

BlackJack hat geschrieben:die Klasse dazu sieht sehr langweilig aus
VB6 User-defined Types sind langweilige Klassen, d.h. Klassen ohne Methoden (außer einem Initialisierer). Sie entsprechen in etwa den C structs: http://www.vb6.us/tutorials/user-defined-types-udt-vb.
a fool with a tool is still a fool, www.magben.de, YouTube
BlackJack

@MagBen: Ich weiss. Deswegen habe ich das ja geschrieben.

@Papageno: Du kannst jedes Objekt als Element in eine Liste stecken. Sogar Klassen, aber Du möchtest hier eher Exemplare von einer Klasse verwenden statt die Klasse selbst. Denn Klassen sind in Python auch Objekte, wie alles andere was man an einen Namen binden kann.
Papageno
User
Beiträge: 33
Registriert: Sonntag 21. Dezember 2014, 10:53

ok, habs so halbwegs hinbekommen. Nachdem die Problematik ähnlich des Lottozahlenproblems ist (Anstatt 6 aus 49 eben Messwerte aus Kanäle) habe ich mich von dem Lottothread beeinflussen lassen und zur Verständlichkeit darauf umgebaut

1. Klasse erzeugt

Code: Alles auswählen

class clzahlen(object):                                                             # Klasse für 5 Zahlen und 2 Zusatzzahlen
    def __init__(self, lzahl1, lzahl2, lzahl3, lzahl4, lzahl5, lstern1, lstern2):   # Variablen an Klasse übergeben
        self.lzahl1  = lzahl1                                                       # Variablen Namen zuweisen 
        self.lzahl2  = lzahl2                                                       # ...
        self.lzahl3  = lzahl3
        self.lzahl4  = lzahl4
        self.lzahl5  = lzahl5
        self.lstern1 = lstern1
        self.lstern2 = lstern2
2. Klasse in Liste und befüllt

Code: Alles auswählen

def ZiehungReihe(wieoft):
    lzahlen = []                                        # Merkerliste
    lsterne = []                                        # Merkerliste
    lziehungen = []                                     # Rückgabe

    for num in (range(wieoft)):
        lzahlen = Einzelziehung(5,50)                   # Schreiben von Zufallszahlen in Liste (später dann Messwerte aus Datei 1)
        lsterne = Einzelziehung(2,10)                   # Schreiben von Zufallszahlen in Liste (später dann Messwerte aus Datei 2)
        lziehungen.append(clzahlen(lzahlen[0],lzahlen[1],lzahlen[2], lzahlen[3], lzahlen[4], lsterne[0], lsterne[1]))                     # der Liste die aktuelle Klasse zuweisen
    return(lziehungen)                                  # Rückgabe der Liste mit den Klasseneinträgen
3. Die Ausgabe der Daten

Code: Alles auswählen

    alleziehungen =[]                                               # Liste initialisieren
    alleziehungen = ZiehungReihe(5)                             # Testaufruf mit 5 Reihen
    for num in range(len(alleziehungen)):                       # Für alle Einträge in der Liste
        for name in alleziehungen[num].__dict__:                # Für alle Variablen (Attribute?) in der Klasse
            print(name, alleziehungen[num].__dict__[name])      # Ausgabe Variablenname der Klasse und Wert dessselben
Was mir hier nicht gefällt, ist dass die Klasse fix ist. Ich habe aber mal 8, 12 oder gar 24 Kanäle (sollte beim Aufruf von lzahlen = Einzelziehung(5,50) stattfinden und bei lziehungen.append(clzahlen(lzahlen[0],lzahlen[1],lzahlen[2], lzahlen[3], lzahlen[4], lsterne[0], lsterne[1])) eben auch dynamisch befüllt werden. Die Namensräume könnte ich mir als Temp1 ... Tempx oder Vib1... Vibx vorstellen, also immer ein Initial und angehängter Index. (Ebenso fehlen noch Datum und andere mit den Werten verbundene Parameter, aber die wären wirklich definierbare Variablen)

Geht das überhaupt? Und wenn ja, wie :mrgreen: Habe hierzu (noch) nix literarisches gefunden.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Papageno: Was Du machen willst, wird mir nicht klar, weil Du nur Code zeigst, der furchtbar schlecht ist und aus dem man nichts lesen kann,und die Bezeichner auch noch von einem anderen Problem übernommen sind (Lotto).

Wenn Du eine Liste mit Zahlen hast, nimmst Du eine Liste und nicht 5, 8 oder 13 Variablen mit einer Zahl im Namen. Dann hast Du auch kein Problem damit, dass sich die Anzahl ändert. Damit ist die Klasse auch überflüssig. Du solltest Dich in der Namensgebung an PEP8 halten, dann ist auch klar, was hier Funktionen und was Klassen sind.
BlackJack

@Papageno: Das sieht alles sehr Merkwürdig aus. Es macht keinen Sinn Namen an leere Listen zu binden die niemals benutzt werden. Das solltest Du sein lassen.

Die Ausgabe ist absolut gruselig. Da haben wir das ``for i in range(len(sequence))`` „anti pattern” und direkte Zugriffe auf `__dict__`. Dieser Code würde auch mehr ausgeben als Du haben möchtest. Attribute sind alle Werte die auf einem Objekt abrufbar sind, also auch Methoden.
Papageno
User
Beiträge: 33
Registriert: Sonntag 21. Dezember 2014, 10:53

@Sirius3: Dass der Code verbesserungswürdig ist steht außer Frage. Ich mach erst seit kurzem mit Python rum. PEP8 führe ich so nacheinander ein, bin halt altlastig.
Also Ziel ist folgendes: Ich bekomme Daten aus Messgeräten und SPS, meist unstrukturiert und mit kryptischen Bezeichnern. Bestenfalls als CSV mit Name1; Name2;... in der ersten Zeile und Wert1;Wert2;... in den weiteren Zeilen. Aus mehreren Dateien (oder Online) werden diese dann zu einem Datensatz verknotet. Aber bis dahin muss einiges passieren, was hier erstmal nix zur Sache tut.
Zur besseren Les- und Programmierbarkeit möchte ich diese eben in eine Liste aus Klassenmitgliedern stopfen um dann später eine Auswahl treffen zu können, welche Daten grafisch miteinander angezeigt werden sollen. Z.B. eine Listbox mit den Variablennamen anklicken und rechts daneben dann die Graphen darstellen. Die Klasse soll somit dynamische Variablennamen bekommen, die ich später auch als Auswahlliste benutzen kann.

@BlackJack:
Es macht keinen Sinn Namen an leere Listen zu binden die niemals benutzt werden. Das solltest Du sein lassen.
Das möchte ich ja sein lassen, weis aber nicht wie es besser geht... Methoden könnten man namentlich von den Werten unterscheiden und dadurch filtern.
BlackJack

@Papageno: Wenn die Namen dynamisch sind, dann nimm ein Wörterbuch und keine Klasse. Machst Du ja letztendlich sogar in Deinem Code in dem Du versuchst direkt auf `__dict__` zuzugreifen.

Das Zitat aus meinem Beitrag passt irgendwie so gar nicht zu der Antwort die Du darunter geschrieben hast‽
Papageno
User
Beiträge: 33
Registriert: Sonntag 21. Dezember 2014, 10:53

@BlackJack: Mit meinem bescheidenen Wissen nahm ich an dass du mit den leeren Listen meine Zuweisung meinst. Oder meine Merkerliste? Da hast du recht. Nur lziehungen muss aber vorher erzeugt werden, sonst gibts Fehler :evil: Schon was verbessert. Aber insgesamt kommt es mir (noch) nicht auf Schönheit, sondern Funktion an.
Antworten