Python-Objekt iterieren Pythonobjekte to Dict umwandeln

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
Cheefrocker
User
Beiträge: 6
Registriert: Freitag 10. Oktober 2008, 08:43

Hallo zusammen,
ich möchte von beliebigen Objekte und deren Attribute(Key, Value) auslesen und in einem Parser verarbeiten können. Dabei kenne ich die Attributenamen natürlich nicht.
Wie kann ich aus den Objekten z.b ein Dict oder eine Liste die ich verarbeiten kann?
z.b.

Code: Alles auswählen

Class FirstElement(object):
    vorname = "Heinz"
    nachname = "Mustermann"

Class SecondElement(object):
    gewicht = 40
    geschlecht = "Mann"

main():
    first = FirstElement()
    second = FirstElement()
    myparser.parse(first)
    # Ausgabe waere z.b {'vorname':'Heinz', nachname = "Mustermann"}
    myparser.parse(second)
   # Ausgabe waere z.b {'gewicht':40, geschlecht = "Mann"}

Für Tipps und Anregungen bin ich dankbar!°
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Code: Alles auswählen

In [1]: class FirstElement(object):
   ...:     def __init__(self, vorname, nachname):
   ...:         self.vorname = vorname
   ...:         self.nachname = nachname
   ...:         
   ...:         

In [2]: first = FirstElement('Heinz', 'Mustermann')

In [3]: first.vorname
Out[3]: 'Heinz'

In [4]: first.nachname
Out[4]: 'Mustermann'

In [5]: first.__dict__
Out[5]: {'nachname': 'Mustermann', 'vorname': 'Heinz'}
Cheefrocker
User
Beiträge: 6
Registriert: Freitag 10. Oktober 2008, 08:43

Danke für dein Post!
Das Problem hierbei ist, das die Objekte instanziert sind und ich nicht davon ausgehen kann das diese ein __init__(...) haben.

Daher klappt diese Variante nicht.


Folgendes habe ich gefunden, was für einfache Klassen klappt:

Code: Alles auswählen

def props(obj):
    pr = {}
    for name in dir(obj):
        value = getattr(obj, name)
        if not name.startswith('__') and not inspect.ismethod(value):
            pr[name] = value
     
    return pr

print props(first)
print props(second)
Das Problem ergibt sich bei dieser Variante wenn ich eine Klasse hätte die wie folgt aussieht:

Also ein Klasse die weitere Klassen beinhaltet:

Code: Alles auswählen

class ThirdElement(object):
    hallo = "test" #klappt
    welt = "nichts da" #klappt
    pers = FirstElement() # Klappt nicht...
    
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich möchte lieber nicht wissen, wozu du das brauchst, aber so sollte es klappen:

Code: Alles auswählen

dict((name, value) for (name, value) in obj_instance.__class__.__dict__.items() if not name.startswith('__') and not inspect.isfunction(value))
BlackJack

@Cheefrocker: Ob die eine `__init__()` haben ist ja auch nicht das entscheidende sondern ob sie ein `__dict__` haben.

Deine Begrifflichkeiten sind übrigens ein wenig durcheinander. Was willst Du da überhaupt erreichen?
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

@snafu Für sowas nimmt man besser collections.namedtuple
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

DasIch hat geschrieben:@snafu Für sowas nimmt man besser collections.namedtuple
Ich habe ihn so verstanden, dass er keine Änderungen an den erhaltenen Exemplaren selbst vornehmen kann.
Cheefrocker
User
Beiträge: 6
Registriert: Freitag 10. Oktober 2008, 08:43

Hallo Leute,
folgendes will ich erreichen:

Ich will einen Parser schreiben der aus Objekten und deren Attribute ein XML-Dokument baut.

Also eine Klasse die so so aufgebaut ist:

Code: Alles auswählen

class Kind(object):
    alter = 5

class Person(object):
    vorname = "Heinz"
    nachname = "Mustermann"
    kind = Kind()
Soll eine XML-Datei ergeben die so aufgebaut ist:

<Person>
<vorname>Heinz</vorname>
<nachname>Mustermann</nachname>
<kind>
<alter>5</alter>
</kind>

Dabei will ich ein Parser schreiben der beliebige Objekte in die XML-Struktur wandelt und auch mit unterobjekten klar kommt. Vielleicht wäre das mit Rekursion zu lösen, aber auf einfache Objekte klappt ja die props-Methode.


</Person>
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Schlimmer Fall von Klassenmissbrauch.

Sind das wirklich harte Anforderungen oder kannst du daran drehen?

Extrapoliere ich das richtig und du hast dann fuer jede Person eine Klasse `Person`? Wenn ja, kannst du eigtl schon aufhoeren ueber die Python-Semantik zum Ziel zu kommen und musst selbststaendig den Quelltext parsen. Mehrere `Person`en in einem Modul wuerden sich ja ueberschreiben.
Cheefrocker
User
Beiträge: 6
Registriert: Freitag 10. Oktober 2008, 08:43

@ cofi :?:

Klasse Person war nur ein Beispiel für eine Klasse. Habe deine Frage nicht ganz verstanden.ich kann es drehen wie ich will. Ich wollte halt ein XML-Export von Pythonobjekten machen, ohne die XML-Datei manuell aufzubauen. Wenn es zu kompliziert wird, lass ich es bleiben und werds per Hand machen.

Mein Parser soll mit Objekten, Dicts und Listen klar kommen und daraus eine schöne wollgeformte XML-Datei bauen. Dabei soll dem Parser egal sein ob ich ein Object Person, ein Object Kind oder ein anderes Object habe.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ist ja quasi das Gegenteil von der objectify-API von lxml. Das muss man doch auch zur Serailisierung nutzen können...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Es könnte eventuell auch ein Blick in Module wie `json`, `pickle` oder `pprint` Ideen dazu liefern. Vor allem wohl `pickle`.
BlackJack

@Cheefrocker: Du zeigst da immer Klassen, das verwirrt viele hier wohl. Eine Klasse `Person` mit *Klassenattributen* `vorname`, `nachmane`, usw. ist halt ein sehr unsinniges Beispiel.

Ansonsten musst Du natürlich eine rekursive Funktion schreiben, wenn Du eine rekursive Datenstruktur serialisieren willst. Wenn es nicht nur eine Hierarchische ist, sondern beliebige Objektgraphen vorkommen können, wird es noch ein wenig komplizierter, denn dann musst Du ja auch irgendwie mit "Kreisen" umgehen können. Und was machst Du wenn ein und das selbe Objekt mehrfach vorkommt? Zweimal serialisieren, oder irgendwie einen Verweis in das XML einbauen?

In Deinem Beispiel sicherst Du die Typen gar nicht. Man kann aus dem XML nicht erkennen ob `alter` beim Kind eine Zahl oder eine Zeichenkette war.

`pickle` wurde ja schon vorgeschlagen. So etwas möchtest Du haben, nur mit XML als Zielformat.

Da musst Du natürlich auch noch auf die ganzen Eigenheiten von XML aufpassen. Zum Beispiel kann man darin nicht beliebige Bytestrings speichern. Und der XML-Parser darf die Sequenzen für Zeilenenden nach belieben verändern.

Mit Deiner Verwendung des Begriffs "Parser" habe ich so meine Schwierigkeiten -- üblicherweise bezeichnet man damit Code der Quelltext verarbeitet und Objekte ausspuckt und nicht umgekehrt.
Antworten