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.
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

Samstag 3. März 2007, 00:21

Hallo gerold!

danke für die guten Beispiele.
Eine SQL-Abfrage braucht eher selten solche Objekte, da man ja in SQL 95% aller Filter, Berechnungen etc. in die Abfrage des DBMS einbauen kann.
Aber nehmen wir mal eine XML-Datei. Wenn ich diese einlesen(parsen) möchte, möchte ich diese auch als Objekt betrachten. Etwa so:

Code: Alles auswählen

class Address(object):
    Adressen = {}   
    first_name = None
    last_name = None
Wenn ich Deine Beispiele betrachte(ich habe sie noch nicht vollständig erfasst), sehe ich zwei Varianten.
Du erstellst zwei Klassen oder Du füllst einen Container außerhalb der Objekte. Es ist sicher eine Betrachtungsweise. Mir wäre es naheliegender, all dies in einer Klasse zu vereinen. Machbar sollte es doch sein.
Zu netdoobage's Problem. Im DBMS sollte jede Tabelle einen sogenannten primary Key besitzen. Dieser kann doch vorzugsweise der Key im Dictionary der Tupel werden.

Gruß P.
BlackJack

Samstag 3. März 2007, 10:15

Ich habe glaube ich immer noch nicht verstanden was Du willst. Ein `Adress`-Objekt, das gleichzeitig sowohl eine konkrete Adresse als auch alle Adressen ist? Das klingt gar nicht gut.
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

Sonntag 4. März 2007, 14:59

BlackJack hat geschrieben:Ich habe glaube ich immer noch nicht verstanden was Du willst. Ein `Adress`-Objekt, das gleichzeitig sowohl eine konkrete Adresse als auch alle Adressen ist? Das klingt gar nicht gut.
So gesehen hast Du vollkommen recht. In meiner Betrachtungsweise sehe ich wohl eher die Abfrage, die Datei .. als Objekt. Meine objektorientierte Sichtweise muß noch trainiert werden :)

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

Dienstag 6. März 2007, 14:18

Hallo @ all,

mit einem Dictionary die ganze Geschichte zu lösen klappt leider auch nicht. Da die Abfragen aus der Datenbank(können mehrmals die gleichen sein) die gleichen Feldnamen aufweisen und ich somit die Variablen immer wieder überschreibe(wenn ich sie aus dem Dictionary den Attributen zuweise). Mache jetzt erstmal an einer anderen Baustelle weiter...

Vielen Dank an alle die mir geholfen haben!

Beste Grüße
netdoobage
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

Donnerstag 8. März 2007, 13:26

netdoobage hat geschrieben:Hallo @ all,

mit einem Dictionary die ganze Geschichte zu lösen klappt leider auch nicht. Da die Abfragen aus der Datenbank(können mehrmals die gleichen sein) die gleichen Feldnamen aufweisen und ich somit die Variablen immer wieder überschreibe(wenn ich sie aus dem Dictionary den Attributen zuweise)
...
Wenn in der DB kein eindeutiges(unique) Feld existiert, gehe ich von einem DesignProblem aus.

Gruß P.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Donnerstag 8. März 2007, 14:22

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

Freitag 9. März 2007, 13:00

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

Freitag 9. März 2007, 13:28

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

Freitag 9. März 2007, 13:32

@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:

Freitag 9. März 2007, 13:51

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

Freitag 16. März 2007, 11:49

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