Je cherche un moyen élégant d'obtenir des données en utilisant l'accès aux attributs sur un dict avec quelques dict et listes imbriqués (c'est-à-dire une syntaxe d'objet de style javascript).
Par exemple:
>>> d = {'a': 1, 'b': {'c': 2}, 'd': ["hi", {'foo': "bar"}]}
Devrait être accessible de cette manière:
>>> x = dict2obj(d)
>>> x.a
1
>>> x.b.c
2
>>> x.d[1].foo
bar
Je pense que ce n'est pas possible sans récursivité, mais quelle serait une bonne façon d'obtenir un style d'objet pour les dict?
python
object
dictionary
Marc
la source
la source
from_
plutôt que_from
selon PEP 8 .getattr(x, 'from')
au lieu de renommer l'attribut.d1.b.c
), je pense qu'il est clair que vous devriez utiliser quelque chose d'une bibliothèque, par exemple nommétuple de collections , comme cette réponse le suggère, .. .Réponses:
Mise à jour: dans Python 2.6 et versions ultérieures, déterminez si la
namedtuple
structure des données convient à vos besoins:L'alternative (contenu de la réponse d'origine) est:
Ensuite, vous pouvez utiliser:
la source
Struct
s imbriqués à partir de dictionnaires imbriqués, mais en général le type de la valeur peut être n'importe quoi. La clé est limitée à un emplacement d'objetargparse.Namespace
(qui a également défini__eq__
,__ne__
,__contains__
).la source
if isinstance(b, (list, tuple)):
obj
classe d'hériter deargparse.Namespace
fonctionnalités supplémentaires telles que la représentation de chaînes lisibles.Étonnamment, personne n'a mentionné Bunch . Cette bibliothèque est exclusivement destinée à fournir un accès au style d'attribut aux objets dict et fait exactement ce que l'OP veut. Une démonstration:
Une bibliothèque Python 3 est disponible sur https://github.com/Infinidat/munch - Le crédit revient à codyzu
la source
puis ajoutez la récursivité à cela et vous avez terminé.
éditez comme je l'implémenterais:
la source
top_instance = top()
et le retourner là où vous reveneztop
?x
x.b
<class '__main__.new'>
Il existe un assistant de collecte appelé
namedtuple
, qui peut le faire pour vous:la source
Peut être utilisé avec n'importe quelle structure séquence / dict / valeur de n'importe quelle profondeur.
la source
def __repr__(self): return '{%s}' % str(', '.join("'%s': %s" % (k, repr(v)) for (k, v) in self.__dict__.iteritems()))
.items()
place de la.iteritems()
ligne 4. (La fonction a été renommée, mais fait essentiellement la même chose )En prenant ce que je pense être les meilleurs aspects des exemples précédents, voici ce que j'ai trouvé:
la source
def __init__(self, dct): for k, v in dct.iteritems(): setattr(self, k, isinstance(v, dict) and self.__class__(v) or v)
ce qui supprime également l'appel explicite àStruct
isinstance(v, dict)
chèque serait mieux carisinstance(v, collections.Mapping)
il peut gérer les futures choses de type dictSi votre dict provient
json.loads()
, vous pouvez le transformer en objet à la place (plutôt qu'en dict) sur une seule ligne:Voir aussi Comment convertir des données JSON en un objet Python .
la source
.loads
si vous avez un énorme objet JSONSi vous souhaitez accéder aux clés de dict en tant qu'objet (ou en tant que dict pour les touches difficiles), faites-le de manière récursive et pouvez également mettre à jour le dict d'origine, vous pouvez faire:
Exemple d'utilisation:
la source
la source
J'ai fini par essayer les deux AttrDict et Bunchbibliothèques et les a trouvés beaucoup trop lents pour mes utilisations. Après qu'un ami et moi avons examiné la question, nous avons constaté que la principale méthode d'écriture de ces bibliothèques entraînait la récurrence agressive de la bibliothèque à travers un objet imbriqué et la création de copies de l'objet dictionnaire. Dans cet esprit, nous avons apporté deux changements clés. 1) Nous avons créé des attributs chargés paresseusement 2) au lieu de créer des copies d'un objet dictionnaire, nous créons des copies d'un objet proxy léger. Ceci est la mise en œuvre finale. L'augmentation des performances de l'utilisation de ce code est incroyable. Lorsque j'utilise AttrDict ou Bunch, ces deux bibliothèques à elles seules ont consommé respectivement 1/2 et 1/3 de mon temps de demande (quoi !?). Ce code a réduit ce temps à presque rien (quelque part dans la plage de 0,5 ms). Cela dépend bien sûr de vos besoins,
Voir l'implémentation originale ici par https://stackoverflow.com/users/704327/michael-merickel .
L'autre chose à noter, c'est que cette implémentation est assez simple et n'implémente pas toutes les méthodes dont vous pourriez avoir besoin. Vous devrez les écrire comme requis sur les objets DictProxy ou ListProxy.
la source
x.__dict__.update(d)
devrait bien faire.la source
__dict__
: essayezobject().__dict__
et vous obtiendrezAttributeError: 'object' object has no attribute '__dict__'
Vous pouvez tirer parti du
json
module de la bibliothèque standard avec un crochet d'objet personnalisé :Exemple d'utilisation:
Et ce n'est pas strictement en lecture seule comme c'est le cas avec
namedtuple
, c'est-à-dire que vous pouvez changer les valeurs - pas la structure:la source
json.JSONEncoder
etobject_hook
.Cela devrait vous aider à démarrer:
Cela ne fonctionne pas encore pour les listes. Vous devrez encapsuler les listes dans une UserList et surcharger
__getitem__
pour encapsuler les dict.la source
if isinstance(d, list)
clause deAnon
la réponse de.Je sais qu'il y a déjà beaucoup de réponses ici et je suis en retard à la fête, mais cette méthode convertira récursivement et «en place» un dictionnaire en une structure de type objet ... Fonctionne en 3.xx
la source
la source
Permettez-moi d'expliquer une solution que j'ai presque utilisée il y a quelque temps. Mais d'abord, la raison pour laquelle je ne l'ai pas est illustrée par le fait que le code suivant:
donne cette erreur:
Parce que "de" est un mot clé Python, il y a certaines clés de dictionnaire que vous ne pouvez pas autoriser.
Maintenant, ma solution permet d'accéder aux éléments du dictionnaire en utilisant directement leurs noms. Mais il vous permet également d'utiliser la "sémantique des dictionnaires". Voici le code avec un exemple d'utilisation:
la source
Ancien Q & A, mais je reçois quelque chose de plus à parler. Il semble que personne ne parle de dict récursif. Voici mon code:
la source
Je voulais télécharger ma version de ce petit paradigme.
Il conserve les attributs du type importé dans la classe. Ma seule préoccupation serait d'écraser les méthodes du dictionnaire dans votre analyse. Mais sinon, ça semble solide!
la source
df.a
ça ne marche même pas.Cela fonctionne aussi bien aussi
la source
Voici une autre façon de mettre en œuvre la suggestion originale de SilentGhost:
la source
Je suis tombé sur le cas dont j'avais besoin pour convertir récursivement une liste de dict en liste d'objets, donc sur la base de l'extrait de Roberto ici ce qui a fait le travail pour moi:
Notez que tout tuple sera converti en son équivalent de liste, pour des raisons évidentes.
J'espère que cela aide quelqu'un autant que toutes vos réponses pour moi, les gars.
la source
Qu'en est-il de simplement attribuer votre
dict
à l'__dict__
objet vide?Bien sûr, cela échoue sur votre exemple de dict imbriqué, sauf si vous le faites récursivement:
Et votre exemple d'élément de liste était probablement censé être une
Mapping
, une liste de paires (clé, valeur) comme ceci:la source
Voici une autre implémentation:
[Modifier] Bit manquant sur la gestion des dictés dans les listes, pas seulement d'autres dictés. Ajout d'un correctif.
la source
Usage:
la source
Que dis-tu de ça:
Cela peut ensuite être utilisé comme ceci:
la source
Je pense qu'un dict se compose de nombre, de chaîne et de dict est suffisant la plupart du temps. J'ignore donc la situation où les tuples, les listes et les autres types n'apparaissent pas dans la dimension finale d'un dict.
Compte tenu de l'héritage, combiné à la récursivité, il résout le problème d'impression de manière pratique et fournit également deux façons d'interroger des données, une façon de modifier les données.
Voir l'exemple ci-dessous, un dict qui décrit certaines informations sur les étudiants:
Résultats:
la source
En règle générale, vous souhaitez mettre en miroir la hiérarchie dict dans votre objet, mais pas la liste ou les tuples qui sont généralement au niveau le plus bas. Voilà donc comment je l'ai fait:
Nous faisons donc:
et obtenir:
x.b.b1.x
1x.c
[«salut», «bar»]la source
Mon dictionnaire est de ce format:
Comme on peut le voir, j'ai des dictionnaires imbriqués et une liste de dict . En effet, l'addr_bk a été décodé à partir des données du tampon de protocole converties en dict python à l'aide de lwpb.codec. Il y a un champ optionnel (par exemple email => où la clé peut ne pas être disponible) et un champ répété (par exemple téléphone => converti en liste de dict).
J'ai essayé toutes les solutions proposées ci-dessus. Certains ne gèrent pas bien les dictionnaires imbriqués. D'autres ne peuvent pas imprimer facilement les détails de l'objet.
Seule la solution, dict2obj (dict) de Dawie Strauss, fonctionne le mieux.
Je l'ai un peu amélioré pour gérer quand la clé est introuvable:
Ensuite, je l'ai testé avec:
la source
Construire ma réponse à " python: Comment ajouter dynamiquement une propriété à une classe? ":
Vous appelez
makedata
le dictionnaire que vous souhaitez convertir, ou peut-être entrydata
fonction de ce que vous attendez en entrée, et il crache un objet de données.Remarques:
trydata
si vous avez besoin de plus de fonctionnalités.x.a = {}
ou similaire.la source