De manière récursive convertir python objet graphique à dictionnaire
Je suis en train de convertir les données à partir d'un simple objet graphique dans un dictionnaire. Je n'ai pas besoin de saisir des informations ou des méthodes et je n'ai pas besoin d'être en mesure de convertir un objet nouveau.
J'ai trouvé cette question sur la création d'un dictionnaire à partir d'un objet de champs, mais il ne le fait pas de manière récursive.
Étant relativement nouveau pour python, je pense que ma solution est peut être moche, ou unpythonic, ou rompu en quelque manière obscure, ou tout simplement vieux NIH.
Ma première tentative est apparu à travailler jusqu'à ce que je l'ai essayé avec les listes et les dictionnaires, et il semblait plus facile de vérifier si l'objet passé en avait un dictionnaire interne, et si non, juste le traiter comme une valeur (plutôt que de faire tout ce qui isinstance de la vérification). Mes précédentes tentatives de ne pas répéter dans les listes des objets:
def todict(obj):
if hasattr(obj, "__iter__"):
return [todict(v) for v in obj]
elif hasattr(obj, "__dict__"):
return dict([(key, todict(value))
for key, value in obj.__dict__.iteritems()
if not callable(value) and not key.startswith('_')])
else:
return obj
Cela semble mieux fonctionner et ne nécessite pas des exceptions, mais encore une fois je ne suis toujours pas sûr si il y a des cas ici, je ne suis pas au courant de l'endroit où elle tombe.
Toutes les suggestions seront très appréciés.
- en python, il n'est pas si mal utiliser les exceptions et parfois, il peut simplifier le codage, un pythonic façon - l'aeap (plus Facile de Demander Pardon que la Permission)
- cas particulier pourrait être lorsque l'objet a slots, édité répondre
- point de pris, mais l'exception chose est un peu une guerre sainte, et j'ai tendance vers préférant ne jamais être jeté à moins que quelque chose est vraiment exceptionnelle, plutôt que d'attendre le flux du programme. chacune de leur propre sur celui-ci 🙂
- oui surtout que c'est un style, mais parfois exception peut vraiment tout simplement le code par exemple, lors de l'intérieure de la plupart des fonctions de communiquer thru exceptions, et parfois il peut accélérer les choses si 99.99 % des objets ont dict, dans ce cas, au lieu de vérifier les 99,99% de temps de dict, de vérifier l'exception .01% du temps
Vous devez vous connecter pour publier un commentaire.
Une fusion de ma propre tentative et indices dérivés de Anurag Uniyal et Lennart Regebro réponses qui fonctionne le mieux pour moi:
iteritems()
devrait êtreitems()
, et[todict(v, classkey) for v in obj]
(ligne 10) tente d'effectuer une itération des caractères dans les chaînes, est fixée à:elif hasattr(obj, "__iter__") and not isinstance(obj, str)
.Une ligne de code pour convertir un objet en JSON de manière récursive.
Je ne sais pas quel est le but de la vérification de basestring ou d'un objet? aussi dict ne contiennent aucune callables sauf si vous avez attributs pointant vers ces callables, mais dans ce cas, n'est-ce pas partie de l'objet?
donc, au lieu de vérifier les différents types et les valeurs, laissez todict convertir l'objet et s'il lève l'exception, de l'utilisateur à l'origine de la valeur.
todict ne raise exception si obj n'a pas dict
par exemple,
il imprime {'b1': 1, 'b2': 2, 'o1': {'a1': 1}}
il peut y avoir quelques autres cas à considérer, mais il peut être un bon début
cas spéciaux
si un objet utilise des machines à sous alors vous ne serez pas en mesure d'obtenir dict par exemple
correctif pour les fentes des cas peut être utiliser dir() au lieu d'utiliser directement la dict
En Python il existe de nombreuses façons de fabriquer des objets se comportent un peu différemment, comme les metaclasses et autres joyeusetés, et il peut remplacer getattr et d'avoir ainsi "magique" attributs vous ne pouvez pas voir à travers dict, etc. En bref, il est peu probable que vous allez obtenir une complète à 100% de l'image dans le cas générique avec quelle que soit la méthode que vous utilisez.
Par conséquent, la réponse est: Si cela fonctionne pour vous dans le cas d'utilisation que vous avez maintenant, alors que le code est correct. 😉
De faire un peu plus générique code que vous pourriez faire quelque chose comme ceci:
Quelque chose comme ça. Ce code n'est pas testé, si. Ce n'est pas toujours le cas lorsque vous remplacez getattr, et je suis sûr qu'il ya beaucoup plus de cas que cela se complique couvre pas et ne peut pas être recouvrable. 🙂
Je me rends compte que cette réponse est un peu trop tard, mais j'ai pensé qu'il pourrait être utile de partager car c'est un Python 3.3,+ compatible modification de la solution d'origine par @Shabbyrobe qui a généralement bien fonctionné pour moi:
Si vous n'êtes pas intéressé par appelable attributs, par exemple, ils peuvent être supprimés dans le dictionnaire de la compréhension:
Lentement mais de façon simple de faire cela est d'utiliser
jsonpickle
pour convertir l'objet d'une chaîne JSON et puisjson.loads
pour la convertir à un dictionnaire python:dict = json.loads(jsonpickle.encode( obj, unpicklable=False ))
Une petite mise à jour pour Shabbyrobe de réponse pour le faire fonctionner pour
namedtuple
s: