Mein Wörterbuch ist von diesem Format:
addr_bk = {
'person': [
{'name': 'Andrew', 'id': 123, 'email': 'andrew@mailserver.com',
'phone': [{'type': 2, 'number': '633311122'},
{'type': 0, 'number': '97788665'}]
},
{'name': 'Tom', 'id': 456,
'phone': [{'type': 0, 'number': '91122334'}]},
{'name': 'Jack', 'id': 7788, 'email': 'jack@gmail.com'}
]
}
Wie Sie sehen können, habe ich verschachtelte Wörterbücher y Liste von Diktaten . Dies liegt daran, dass addr_bk aus Protokollpufferdaten dekodiert wurde, die mit lwpb.codec in ein Python-Dict umgewandelt wurden. Es gibt optionale Felder (z.B. email => wo der Schlüssel nicht verfügbar sein kann) und wiederholte Felder (z.B. phone => konvertiert in eine Liste von dict).
Ich habe alle oben vorgeschlagenen Lösungen ausprobiert. Einige kommen mit den verschachtelten Wörterbüchern nicht zurecht. Andere können die Objektdetails nicht einfach drucken.
Nur die Lösung dict2obj(dict) von Dawie Strauss funktioniert am besten.
Ich habe die Funktion ein wenig erweitert, damit sie funktioniert, wenn der Schlüssel nicht gefunden wird:
# Work the best, with nested dictionaries & lists! :)
# Able to print out all items.
class dict2obj_new(dict):
def __init__(self, dict_):
super(dict2obj_new, self).__init__(dict_)
for key in self:
item = self[key]
if isinstance(item, list):
for idx, it in enumerate(item):
if isinstance(it, dict):
item[idx] = dict2obj_new(it)
elif isinstance(item, dict):
self[key] = dict2obj_new(item)
def __getattr__(self, key):
# Enhanced to handle key not found.
if self.has_key(key):
return self[key]
else:
return None
Dann habe ich es mit getestet:
# Testing...
ab = dict2obj_new(addr_bk)
for person in ab.person:
print "Person ID:", person.id
print " Name:", person.name
# Check if optional field is available before printing.
if person.email:
print " E-mail address:", person.email
# Check if optional field is available before printing.
if person.phone:
for phone_number in person.phone:
if phone_number.type == codec.enums.PhoneType.MOBILE:
print " Mobile phone #:",
elif phone_number.type == codec.enums.PhoneType.HOME:
print " Home phone #:",
else:
print " Work phone #:",
print phone_number.number
6 Stimmen
Ich habe vor kurzem versucht, etwas Ähnliches zu tun, aber ein wiederkehrender Wörterbuchschlüssel ("from" - ein Python-Schlüsselwort) hat mich daran gehindert, es zu tun. Denn sobald man versuchte, mit "x.from" auf dieses Attribut zuzugreifen, erhielt man einen Syntaxfehler.
3 Stimmen
Das ist in der Tat ein Problem, aber ich kann auf "from" verzichten, um das Leben einfacher zu machen, wenn ich auf große Diktatkonstrukte zugreife:) die Eingabe von x['a']['d'][1]['foo'] ist wirklich lästig, also gilt x.a.d[1].foo. wenn Sie from benötigen, können Sie über getattr(x, 'from') darauf zugreifen oder stattdessen _from als Attribut verwenden.
7 Stimmen
from_
statt_from
laut PEP 8 .1 Stimmen
Sie können verwenden
getattr(x, 'from')
statt der Umbenennung des Attributs.4 Stimmen
Die meisten dieser "Lösungen" scheinen nicht zu funktionieren (selbst die akzeptierte, erlaubt keine verschachtelten
d1.b.c
), ist es meiner Meinung nach klar, dass Sie etwas aus einer Bibliothek verwenden sollten, z. B. namedtuple aus Sammlungen , como diese Antwort suggeriert, ...2 Stimmen
Bunch - Verwenden Sie ein Python-Dict wie ein Objekt: thechangelog.com/bunch-lets-use-python-dict-like-object