Dynamische Variablenzuweisung

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.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

netdoobage hat geschrieben:@ HWK:
Was ich bis jetzt über die setattr weiß ist, dass für Instanzen einer Klasse automatisch ein Dictionary angelegt wird das die Attribute festhält. Beim Attributzguriff wird in diesem Dictionary gesucht, dann in dem der
Klasse, dann in der Basisklasse. Mit setattr kann ich mir also eigene Attribut Zugriffsfunktionen definieren.
Ist das so richtig???

Falls ja bringt es mich leider nicht weiter denn ich möchte nicht die Attribute benennen so wie es auch gerold
angenommen hat (sorry das ich mein Problem nicht deutlicher beschrieben habe) sondern jeden Tupel zu einer Instanz meiner Basisklasse machen:
Und warum sollte das mit setattr nicht gehen?

Code: Alles auswählen

for key in tupel.iterkeys():
    setattr(self, key, tupel[key])
Das geht natürlich auch entsprechend für das Benennen der Instanzen:

Code: Alles auswählen

class AndereKlasse:
    def __init__(self, tupels):
        for tupel, name in zip(tupels, namen):
            setattr(self, name, BasisKlasse(tupel))
Das wäre dann meines Erachtens aber wirklich Schwachsinn. Da müsste ich mich vollkommen BlackJack anschließen.
MfG
HWK
Benutzeravatar
netdoobage
User
Beiträge: 12
Registriert: Donnerstag 1. März 2007, 15:13

Hallo

Also beim besten Willen - ich bin zu blöd dafür. Ich begreif es einfach nicht.
Aus meiner Datenbankabfrage bekomme ich ein Liste von Dictionarys, d.h. an Stelle eins ist mein erster Datensatz mit den Spaltennamen als Schlüssel und entsprechenden Wert dahinter an Stelle zwei der zweite Datensatz mit den Spaltennamen als Schlüssel und entsprechenden Werten...

[{'auftragid': 12345, 'vierdraht': ' ', 'strasse': 'A-strasse. 25', 'ev': ' 12 ', 'verfahren': 'H13', 'typ': 'Kündigung', 'dtagvertragsnummer': '189abc', 'zweidraht': 'X', 'hvtort': 'Musterort A', 'kunde': 'Hans Mustermann, 'termin': '15.01.2007', 'ort': '0000 Musterort A', 'rufnummer': '123456', 'hvtplz': '00000'}, {'auftragid': 12345, 'vierdraht': ' ', 'strasse': 'B-strasse 33', 'ev': ' 12 ', 'verfahren': 'H13', 'typ': 'Bestellung', 'dtagvertragsnummer': '189abc', 'zweidraht': 'X', 'hvtort': 'Musterort B', 'kunde': 'Hans Mustermann', 'termin': '15.01.2007', 'ort': '00001, Musterort B', 'rufnummer': '56789', 'hvtplz': '00002'}]

Die Spaltennamen sind eindeutig, doch bei einer solchen Abfrage: "select * from word_cudadtag where auftragid=7318937" bekomme ich zwei Datensätze weil: einmal den Datensatz mit der alten Adresse die ich benötige und einmal den Datensatz mit der neuen Adresse die ich ebenfalls benötige. So ähnlich sieht es mit vielen Spalten(hvtplz, hvtort, etc.) aus die für diese Abfrage zutreffen. siehe oben

Instanziere ich nun ein Objekt für diese Abfrage würde ich doch in meiner Klasse die Attribute doppelt belegen und könnte sie im weiteren Programmverlauf nicht mehr sauber voneinander trennen. Stimmt das so?

Nun begreife ich nicht wieso das Schwachsinn ist wenn ich gerne für jeden Datensatz der Abfrage ein eigenes Objekt instanzieren möchte? Und da ich nicht weiß wieviele Datensätze aus der Datenbank kommen sollten die Objektnamen variabel sein. Bei setattr kann ich doch auch nur sagen:

setattr(o,n,v)

setz das Attribut n des Objekts o auf den Wert v und somit habe ich wieder für jeden daten satz den gleichen Namen.

Ihr werdet jetzt sicher denken man ist der nervig aber ich sehe momentan keine andere Lösung meine Denkweise zu ändern/erweitern ohne nochmal nach zu haken.

Vielen Dank an alle
Gruß netdoobage
BlackJack

netdoobage hat geschrieben:Nun begreife ich nicht wieso das Schwachsinn ist wenn ich gerne für jeden Datensatz der Abfrage ein eigenes Objekt instanzieren möchte?
Das ist kein Schwachsinn…
Und da ich nicht weiß wieviele Datensätze aus der Datenbank kommen sollten die Objektnamen variabel sein.
…aber *das* ist Schwachsinn. Warum muss so ein Objekt einen Namen haben? Die kommen genau wie Dein Beispiel oben in eine Liste und gut ist.

Einfachste Möglichkeit ist die `Bunch`-Klasse, sofern als Schlüssel nur Zeichenketten vorkommen, die gültige Namen in Python sind:

Code: Alles auswählen

In [33]: a
Out[33]:
[{'auftragid': 12345,
  'dtagvertragsnummer': '189abc',
  'ev': '  12  ',
  'hvtort': 'Musterort A',
  'hvtplz': '00000',
  'kunde': 'Hans Mustermann',
  'ort': '0000 Musterort A',
  'rufnummer': '123456',
  'strasse': 'A-strasse. 25',
  'termin': '15.01.2007',
  'typ': 'K\xc3\xbcndigung',
  'verfahren': 'H13',
  'vierdraht': '   ',
  'zweidraht': 'X'},
 {'auftragid': 12345,
  'dtagvertragsnummer': '189abc',
  'ev': '  12  ',
  'hvtort': 'Musterort B',
  'hvtplz': '00002',
  'kunde': 'Hans  Mustermann',
  'ort': '00001, Musterort B',
  'rufnummer': '56789',
  'strasse': 'B-strasse 33',
  'termin': '15.01.2007',
  'typ': 'Bestellung',
  'verfahren': 'H13',
  'vierdraht': '   ',
  'zweidraht': 'X'}]

In [34]: class Bunch(object):
   ....:     def __init__(self, data):
   ....:         self.__dict__ = data
   ....:

In [35]: b = map(Bunch, data)

In [36]: b
Out[36]: [<__main__.Bunch object at 0xb7831b8c>,
          <__main__.Bunch object at 0xb7831eac>]

In [37]: c = b[0]

In [38]: c.kunde, c.termin
Out[38]: ('Hans Mustermann', '15.01.2007')
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

@netdoobage: Nochmal als Info zu meinem letzten Posting:
Der 1. Code soll Deine Basisklasse vereinfachen. Du müsstest nur ein paar Keys anpassen und statt nicht vorhandener Keys z.B. Keys mit Leerstring als Value verwenden. Dann müsste es problemlos funktionieren. Hier finde ich setattr auch druchaus sinnvoll, weil es die Klasse erheblich verkürzt und trotzdem den Informationsgehalt der Attributnamen beibehält.
Der 2. Code war für Dein wohl eigentliches Anliegen gedacht. Du baust Dir eine AndereKlasse, die die Abfragen durchführt und dann mit dem Ergebnis tupels beliebige Instanzen der Basisklasse erstellt. Die Instanzen müssen ja irgendwie benannt werden. Dazu habe ich im Beispiel einfach mal eine Liste namen mit den Namen verwendet. Du kannst den Namen natürlich auch x-beliebig bestimmen, z.B. auch irgendwie aus dem tupel. Möglich wäre z.B. ID12345 oder ID12345alt und ID12345neu. Dazu musst Du Dir einfach Code zur Namensfestlegung schreiben. Nur ich denke, hier ist der Informationsgewinn durch solche Namensgebung zu vernachlässigen. Ich würde wirklich ein Dict mit der Auftrags-ID als Schlüssel verwenden. Jeder Eintrag besteht aus zwei 'Unter-Dicts' mit Schlüssel alt bzw. neu, die dann die eigentlichen Infos als Instanz der BasisKlasse enthalten. Der Zugriff ist dann sicher viel einfacher und es bleibt trotzdem eindeutig.
MfG
HWK
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

Worin unterscheidet man den alten von dem neuen Datensatz?
Ich würde die alten Daten in eine neue Tabelle exportieren und löschen. Dann eine Relation zwischen den Tabellen herstellen. Doppelte Datenhaltung ist .. die zweitbeste Lösung.

Edit:

Code: Alles auswählen

                        1   n
 |Stammdaten|-------|Adressen|
            |
            |
            |  1   n
           +-------|Aufträge|

Benutzeravatar
netdoobage
User
Beiträge: 12
Registriert: Donnerstag 1. März 2007, 15:13

Ollleeee, ihr seid die besten! :D

Es hat zwar ein bisschen gedauert bis ich es verstanden hab und gewusst habe wie ich es dann weiter verarbeite und was ich damit alles anstellen kann, aber nichts desto trotz eure Vorschläge sind genial. Ich habe es jetzt so gemacht wie es BlackJack vorgeschlagen hat. Dadurch wurde der Code erheblich kürzer und ich kann trotzdem alles schön dynamisch verarbeiten.

Vielen, vielen Dank @ all

Grüße netdoobage
Antworten