¿Cómo comprobarías si una variable es un diccionario en Python?
Por ejemplo, me gustaría que recorra los valores del diccionario hasta que encuentre un diccionario. Luego, recorre el que encuentra:
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
fuente
fuente
isinstance(v, collections.abc.Mapping)
. En otras palabras, este no es un duplicado exacto de "Diferencias entre isinstance () y type ()".Respuestas:
Podrías usar
if type(ele) is dict
o usarisinstance(ele, dict)
cuál funcionaría si hubieras subclasificadodict
:fuente
isinstance(ele, collections.Mapping)
. Funciona paradict()
,collections.OrderedDict()
ycollections.UserDict()
. El ejemplo en la pregunta es lo suficientemente específico para que funcione la respuesta de Padriac, pero no es lo suficientemente bueno para el caso general.ele.items()
¿por qué verificas el tipo? EAFP / pato tipificación trabaja aquí, sólo envolverfor k,v in ele.items()
entry...except (AttributeError, TypeError)
. Si se eleva la excepción, usted sabeele
no tieneitems
que produce un iterable ...items()
método 2. que resultó ser un iterable y 3. donde cada elemento de ese iterable se puede representar como un 2 -tupla. En este punto, su objeto personalizado ya ha implementado la mitad de un dict. A los efectos del código que figura, solo nos preocupamos por la expansión condicional del elemento anidado, y su objeto personalizado ya lo implementa. (Es un poco irónico que critique el comentario de @Alexander Ryzhov por ser demasiado general, pero ahora plantea un caso general)items()
que producen un iterativo anidado).collections.abc.Mapping
, una nota podría ser apropiada de que son iguales, perocollections.abc
no está disponible antes de Python 3.3.collections.Mapping
alias todavía está disponible en Python 3.6, pero no está documentado, por lo que probablemente uno debería preferircollections.abc.Maping
.Esta es una excelente pregunta, pero es lamentable que la mayoría de los clientes potenciales de respuesta upvoted con una mala recomendación,
type(obj) is dict
.(Tenga en cuenta que tampoco debe usarlo
dict
como un nombre de variable: es el nombre del objeto integrado).Si está escribiendo código que será importado y utilizado por otros, no presuma que usarán el dict incorporado directamente, lo que hace que su presunción haga que su código sea más inflexible y, en este caso, cree errores fácilmente ocultos que no confundirían el programa .
Sugiero encarecidamente, a los fines de la corrección, la facilidad de mantenimiento y la flexibilidad para los futuros usuarios, que nunca tengan expresiones unidiomáticas menos flexibles en su código cuando haya expresiones idiomáticas más flexibles.
is
es una prueba de identidad de objeto . No admite la herencia, no admite ninguna abstracción y no admite la interfaz.Así que proporcionaré varias opciones que sí.
Herencia de apoyo:
Esta es la primera recomendación que haría, ya que permite a los usuarios para abastecer a sus propias subclase de dict, o una
OrderedDict
,defaultdict
oCounter
desde el módulo de las colecciones:if isinstance(any_object, dict):
Pero hay opciones aún más flexibles.
Abstracciones de apoyo:
Esto permite al usuario de su código usar su propia implementación personalizada de una asignación abstracta, que también incluye cualquier subclase de
dict
, y aún así obtener el comportamiento correcto.Usa la interfaz
Comúnmente escuchas el consejo de OOP, "programa a una interfaz".
Esta estrategia aprovecha el polimorfismo de Python o la tipificación de patos.
Entonces, solo intente acceder a la interfaz, capturando los errores esperados específicos (
AttributeError
en caso de que no haya.items
yTypeError
en caso deitems
que no se pueda llamar ) con un respaldo razonable, y ahora cualquier clase que implemente esa interfaz le dará sus elementos (la nota.iteritems()
se ha ido en Python 3):Quizás piense que el uso de tipear pato de esta manera va demasiado lejos al permitir demasiados falsos positivos, y puede ser, dependiendo de sus objetivos para este código.
Conclusión
No lo use
is
para verificar los tipos de flujo de control estándar. Useisinstance
, considere abstracciones comoMapping
oMutableMapping
, y considere evitar la verificación de tipos por completo, usando la interfaz directamente.fuente
El OP no excluyó la variable inicial, por lo que para completar aquí es cómo manejar el caso genérico de procesar un supuesto diccionario que puede incluir elementos como diccionarios.
También siguiendo la forma recomendada pura de Python (3.8) para probar el diccionario en los comentarios anteriores.
fuente
dict.iteritems()
no existe en Python 3, deberías usarlodict.items()
en su lugar.