Como você verificaria se uma variável é um dicionário em Python?
Essa é uma excelente pergunta, mas é lamentável que a resposta mais votada leve a uma recomendação ruim type(obj) is dict
.
(Observe que você também não deve usar dict
como um nome de variável - é o nome do objeto interno.)
Se você estiver escrevendo um código que será importado e usado por outras pessoas, não presuma que eles usarão o dict diretamente - tornando essa suposição mais flexível e, nesse caso, crie bugs facilmente ocultos que não prejudicariam o programa. .
Eu sugiro fortemente, para fins de correção, manutenção e flexibilidade para usuários futuros, nunca ter expressões unidiomatic menos flexíveis em seu código quando houver expressões idiomáticas mais flexíveis.
is
é um teste para a identidade do objeto . Não suporta herança, não suporta abstração e não suporta a interface.
Então, vou fornecer várias opções que o fazem.
Herança de suporte:
Esta é a primeira recomendação gostaria de fazer, porque permite que os usuários forneçam seus próprios subclasse de dict, ou uma OrderedDict
, defaultdict
ou Counter
das coleções módulo:
if isinstance(any_object, dict):
Mas existem opções ainda mais flexíveis.
Abstrações de suporte:
from collections.abc import Mapping
if isinstance(any_object, Mapping):
Isso permite que o usuário do seu código use sua própria implementação personalizada de um mapeamento abstrato, que também inclui qualquer subclasse de dict
, e ainda obtenha o comportamento correto.
Use a interface
Você geralmente ouve os conselhos do OOP, "programa para uma interface".
Essa estratégia aproveita o polimorfismo do Python ou a digitação de patos.
Então, basta tentar acessar a interface, pegando os erros específicos esperado ( AttributeError
no caso, não há .items
e TypeError
no caso items
não é resgatável) com um fallback razoável - e agora qualquer classe que implementa essa interface vai lhe dar os seus itens (nota .iteritems()
é ido em Python 3):
try:
items = any_object.items()
except (AttributeError, TypeError):
non_items_behavior(any_object)
else: # no exception raised
for item in items: ...
Talvez você pense que usar a digitação de pato dessa maneira vá longe demais ao permitir muitos falsos positivos, e pode ser, dependendo dos seus objetivos para este código.
Conclusão
Não use is
para verificar os tipos quanto ao fluxo de controle padrão. Use isinstance
, considere abstrações como Mapping
ou MutableMapping
e evite a verificação de tipo completamente, usando a interface diretamente.