Comment vérifieriez-vous si une variable est un dictionnaire en python?
Par exemple, j'aimerais qu'il parcourt les valeurs du dictionnaire jusqu'à ce qu'il trouve un dictionnaire. Ensuite, parcourez celui qu'il trouve:
dict = {'abc': 'abc', 'def': {'ghi': 'ghi', 'jkl': 'jkl'}}
for k, v in dict.iteritems():
if ###check if v is a dictionary:
for k, v in v.iteritems():
print(k, ' ', v)
else:
print(k, ' ', v)
python
dictionary
Riley
la source
la source
isinstance(v, collections.abc.Mapping)
. En d'autres termes, ce n'est pas un doublon exact de "Différences entre isinstance () et type ()".Réponses:
Vous pourriez utiliser
if type(ele) is dict
ou utiliserisinstance(ele, dict)
ce qui fonctionnerait si vous aviez sousdict
- classé :la source
isinstance(ele, collections.Mapping)
. Il travaille pourdict()
,collections.OrderedDict()
etcollections.UserDict()
. L'exemple de la question est suffisamment précis pour que la réponse de Padriac fonctionne, mais ce n'est pas assez bon pour le cas général.ele.items()
pourquoi vérifiez-vous le type? EAFP / canard frappe fonctionne ici, juste envelopperfor k,v in ele.items()
danstry...except (AttributeError, TypeError)
. Si une exception est levée, vous savez qu'ilele
n'y en a pasitems
qui donne un résultat itérable ...items()
méthode 2. qui se trouve justement produire un itérable et 3. où chaque élément de cet itérable peut être représenté comme un 2 -tuple. À ce stade, votre objet personnalisé a déjà implémenté la moitié d'un dict. Aux fins du code répertorié, nous ne nous sommes souciés que de l'expansion conditionnelle de l'élément imbriqué, et votre objet personnalisé l'implémente déjà. (C'est un peu ironique que vous critiquiez le commentaire de @Alexander Ryzhov pour être trop général mais que vous soulevez maintenant un cas général)items()
qui produisent un itérable imbriqué).collections.abc.Mapping
, une note pourrait être approprié que ce sont les mêmes, maiscollections.abc
ne sont pas disponibles avant Python 3.3.collections.Mapping
L'alias est toujours disponible dans Python 3.6, mais n'est pas documenté, donc probablement on devrait préférercollections.abc.Maping
.Ceci est une excellente question, mais il est regrettable que la plupart des pistes de réponse upvoted avec une mauvaise recommandation,
type(obj) is dict
.(Notez que vous ne devez pas non plus l'utiliser
dict
comme nom de variable - c'est le nom de l'objet intégré.)Si vous écrivez du code qui sera importé et utilisé par d'autres, ne présumez pas qu'ils utiliseront directement le dict intégré - rendant cette présomption rend votre code plus rigide et dans ce cas, créez des bogues facilement cachés qui n'erreront pas le programme en erreur .
Je suggère fortement, à des fins d'exactitude, de maintenabilité et de flexibilité pour les futurs utilisateurs, de ne jamais avoir d'expressions unidiomatiques moins flexibles dans votre code lorsqu'il existe des expressions idiomatiques plus flexibles.
is
est un test d' identité d'objet . Il ne prend pas en charge l'héritage, il ne prend en charge aucune abstraction et il ne prend pas en charge l'interface.Je vais donc fournir plusieurs options qui le font.
Soutenir l'héritage:
C'est la première recommandation que je voudrais faire, car elle permet aux utilisateurs de fournir leur propre sous - classe de dict, ou un
OrderedDict
,defaultdict
ouCounter
des collections module:if isinstance(any_object, dict):
Mais il existe des options encore plus flexibles.
Soutenir les abstractions:
Cela permet à l'utilisateur de votre code d'utiliser sa propre implémentation personnalisée d'un mappage abstrait, qui comprend également n'importe quelle sous-classe de
dict
, tout en obtenant le comportement correct.Utilisez l'interface
Vous entendez généralement les conseils de POO, "programme vers une interface".
Cette stratégie tire parti du polymorphisme ou du typage de canard de Python.
Il suffit donc d'essayer d'accéder à l'interface, d'attraper les erreurs spécifiques attendues (
AttributeError
au cas où il n'y en aurait pas.items
etTypeError
au cas où il neitems
serait pas possible de les appeler) avec un repli raisonnable - et maintenant, toute classe qui implémente cette interface vous donnera ses éléments (la note a.iteritems()
disparu en Python 3):Peut-être pourriez-vous penser que l'utilisation de la saisie de canard comme celle-ci va trop loin en permettant trop de faux positifs, et cela peut l'être, selon vos objectifs pour ce code.
Conclusion
Ne pas utiliser
is
pour vérifier les types de flux de contrôle standard. Utilisezisinstance
, envisagez des abstractions commeMapping
ouMutableMapping
, et évitez complètement la vérification de type, en utilisant directement l'interface.la source
L'OP n'a pas exclu la variable de départ, donc pour être complet, voici comment gérer le cas générique de traitement d'un dictionnaire supposé qui peut inclure des éléments comme dictionnaires.
En suivant également la méthode Python (3.8) recommandée pour tester le dictionnaire dans les commentaires ci-dessus.
la source
dict.iteritems()
n'existe pas dans Python 3, vous devez utiliser à ladict.items()
place.