Comment rendre les membres du dictionnaire Python accessibles via un point "."?
Par exemple, au lieu d'écrire mydict['val']
, j'aimerais écrire mydict.val
.
J'aimerais également accéder aux fichiers imbriqués de cette façon. Par exemple
mydict.mydict2.val
ferait référence à
mydict = { 'mydict2': { 'val': ... } }
python
dictionary
syntax
nested
Bodacydo
la source
la source
d[a][b][c]
est remplacé pard[a, b, c]
.{"my.key":"value"}
? Ou lorsque la clé est un mot clé, comme "de"? Je l'ai envisagé plusieurs fois, et c'est plus de problèmes et de dépannage que d'avantages perçus.Réponses:
Vous pouvez le faire en utilisant cette classe que je viens de créer. Avec cette classe, vous pouvez utiliser l'
Map
objet comme un autre dictionnaire (y compris la sérialisation json) ou avec la notation par points. J'espère vous aider:Exemples d'utilisation:
la source
.iteritems()
à jour vers.items()
AttributeError
si l'attribut n'existe pas. Au lieu de cela, il reviendraNone
.self.update(*args,**kwargs)
. Vous pouvez également ajouter__missing__(self,key): value=self[key]= type(self)(); return value
. Ensuite, vous pouvez ajouter des entrées manquantes en utilisant la notation par points. Si vous voulez qu'il soit sélectionnable, vous pouvez ajouter__getstate__
et__setstate__
hasattr(Map, 'anystring') is true. which means the hasattr would always return True due to overriding
__getattr__`J'ai toujours gardé cela dans un fichier util. Vous pouvez également l'utiliser comme mixage dans vos propres cours.
la source
d = {'foo': {'bar': 'baz'}}; d = dotdict(d); d.foo.bar
renvoie une erreur d'attribut, maisd.foo
fonctionne correctement.python class DotDict(dict): """dot.notation access to dictionary attributes""" def __getattr__(*args): val = dict.get(*args) return DotDict(val) if type(val) is dict else val __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__
get
effet que c'est une mauvaise idée car il reviendraNone
au lieu deInstaller
dotmap
viapip
Il fait tout ce que vous voulez et sous-classe
dict
, il fonctionne donc comme un dictionnaire normal:En plus de cela, vous pouvez le convertir vers et depuis
dict
objets:Cela signifie que si un élément auquel vous souhaitez accéder est déjà en
dict
forme, vous pouvez le transformer enDotMap
pour un accès facile:Enfin, il crée automatiquement de nouvelles
DotMap
instances enfants afin que vous puissiez faire des choses comme ceci:Comparaison avec Bunch
Divulgation complète: je suis le créateur du DotMap . Je l'ai créé car il
Bunch
manquait ces fonctionnalitésDotMap
création , ce qui fait gagner du temps et rend le code plus propre lorsque vous avez beaucoup de hiérarchiedict
et convertir récursivement toutes lesdict
instances enfants enDotMap
la source
{"test.foo": "bar"}
peut être consulté viamymap.test.foo
Ce serait fantastique. Il faudra un peu de régression pour convertir une carte plate en carte profonde, puis lui appliquer DotMap, mais ça vaut le coup!DotMap
avec la saisie semi-automatique fonctionne mieux. J'utilise Sublime Text, qui complète automatiquement les mots clés précédemment saisis.**kwargs
ouc = {**a, **b}
. En fait, il échoue discrètement, il se comporte comme un dictionnaire vide lors de l'extraction.m = DotMap(); m.a = 2; m.b = 3; print('{a} {b}'.format(**m));
et j'ai obtenu l'attendu2 3
. Si vous avez un cas cassé prouvé qui fonctionnedict()
mais pasDotMap()
, veuillez soumettre votre code à l'onglet Problèmes dans GitHub.Dériver de dict et et mettre en œuvre
__getattr__
et__setattr__
.Ou vous pouvez utiliser Bunch qui est très similaire.
Je ne pense pas qu'il soit possible de monkeypatch classe de dict intégré.
la source
Fabric a une implémentation vraiment sympa et minimale . En étendant cela pour permettre un accès imbriqué, nous pouvons utiliser un
defaultdict
, et le résultat ressemble à ceci:Utilisez-le comme suit:
Cela développe un peu la réponse de Kugel à "Dériver de dict et et mettre en œuvre
__getattr__
et__setattr__
". Vous savez maintenant comment!la source
dotdict
qui permet de convertirdict
récursivement un objet existant : gist.github.com/miku/…J'ai essayé ceci:
vous pouvez
__getattribute__
aussi essayer .faire de chaque dict un type de dotdict serait suffisant, si vous voulez l'initier à partir d'un dict multicouche, essayez
__init__
aussi de l' implémenter .la source
def docdict(name):
devant et ensuite `if isinstance (nom, dict): return DotDict (name) returnclass dotdict(dict): def __getattr__(self, name): if name not in self: return None elif type(self[name]) is dict: return JsonDot(self[name]) else: return self[name]
Non. L'accès aux attributs et l'indexation sont des choses distinctes en Python, et vous ne devriez pas vouloir qu'ils fonctionnent de la même manière. Créez une classe (éventuellement celle créée par
namedtuple
) si vous avez quelque chose qui devrait avoir des attributs accessibles et utilisez la[]
notation pour obtenir un élément d'un dict.la source
.
au lieu d'[]
accéder à des structures de données complexes dans les modèles Mako.Si vous souhaitez décaper votre dictionnaire modifié, vous devez ajouter quelques méthodes d'état aux réponses ci-dessus:
la source
__getattr__ = dict.get
En s'appuyant sur la réponse de Kugel et en prenant en compte les mots de prudence de Mike Graham, que se passe-t-il si nous fabriquons un emballage?
la source
Utilisation
SimpleNamespace
:la source
J'aime le Munch et il offre beaucoup d'options pratiques en plus de l'accès aux points.
la source
Je suis récemment tombé sur la ' Box bibliothèque ' qui fait la même chose.
Commande d'installation:
pip install python-box
Exemple:
J'ai trouvé qu'il était plus efficace que d'autres bibliothèques existantes comme dotmap, qui génèrent des erreurs de récursivité python lorsque vous avez de gros dict imbriqués.
lien vers la bibliothèque et les détails: https://pypi.org/project/python-box/
la source
Utilisation
__getattr__
, très simple, fonctionne en Python 3.4.3Production:
la source
Le langage lui-même ne le prend pas en charge, mais parfois c'est toujours une exigence utile. Outre la recette Bunch, vous pouvez également écrire une petite méthode qui peut accéder à un dictionnaire en utilisant une chaîne en pointillés:
qui prendrait en charge quelque chose comme ceci:
la source
Pour s'appuyer sur la réponse d'epool, cette version vous permet d'accéder à n'importe quel dict à l'intérieur via l'opérateur point:
Par exemple,
foo.bar.baz[1].baba
renvoie"loo"
.la source
iteritems()
paritems()
etxrange()
avecrange()
Si l'on décide de convertir définitivement cela
dict
en objet, cela devrait le faire. Vous pouvez créer un objet jetable juste avant d'y accéder.la source
J'ai fini par essayer les deux AttrDict et Bunchbibliothèques et les a trouvés pour être un moyen de ralentir pour mes utilisations. Après qu'un ami et moi nous y sommes penchés, nous avons constaté que la méthode principale pour écrire ces bibliothèques fait que la bibliothèque récursive agressivement à travers un objet imbriqué et fait des copies de l'objet dictionnaire partout. 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, mais si vous utilisez un peu cette fonctionnalité dans votre code,
Voir l'implémentation originale ici par https://stackoverflow.com/users/704327/michael-merickel .
L'autre chose à noter 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
Je voudrais lancer ma propre solution sur le ring:
https://github.com/skorokithakis/jsane
Il vous permet d'analyser JSON en quelque chose auquel vous pouvez accéder
with.attribute.lookups.like.this.r()
, principalement parce que je n'avais pas vu cette réponse avant de commencer à travailler dessus.la source
KeyError
est l'une d'entre elles. Quand on accède à la clé qui n'existe pas, tout ce qu'il a à faire est de retournerNone
similaire au comportement JS. Je suis un grand fan de l'autovivification à la fois pour la lecture et l'écriture. Votre bibliothèque est la plus proche de l'idéal.Pas une réponse directe à la question de l'OP, mais inspirée et peut-être utile pour certains .. J'ai créé une solution basée sur les objets en utilisant le
__dict__
code interne (en aucun cas optimisé)la source
Un moyen simple d'obtenir un accès point (mais pas un accès tableau) est d'utiliser un objet simple en Python. Comme ça:
... et utilisez-le comme ceci:
... pour le convertir en dict:
la source
Cette solution est un raffinement par rapport à celle offerte par epool pour répondre à l'exigence du PO d'accéder aux dict imbriqués de manière cohérente. La solution d'epool ne permettait pas d'accéder aux dict imbriqués.
Avec cette classe, on peut maintenant faire quelque chose comme:
A.B.C.D
.la source
Cela fonctionne également avec les dictés imbriqués et garantit que les dictés ajoutés ultérieurement se comportent de la même manière:
la source
La réponse de @ derek73 est très nette , mais elle ne peut pas être décapée ni copiée (en profondeur), et elle revient
None
pour les clés manquantes. Le code ci-dessous corrige cela.Edit: je n'ai pas vu la réponse ci - dessus qui aborde exactement le même point (vote positif). Je laisse la réponse ici pour référence.
la source
Une solution un peu délicate
la source