Eu tenho um dicionário aninhado. Existe apenas uma maneira de obter valores com segurança?
try:
example_dict['key1']['key2']
except KeyError:
pass
Ou talvez o python tenha um método semelhante get()
ao dicionário aninhado?
python
dictionary
methods
except
Arti
fonte
fonte
except keyerror:
cláusula.Respostas:
Você pode usar
get
duas vezes:Isso retornará
None
se umkey1
oukey2
existir não.Observe que isso ainda pode gerar um
AttributeError
ifexample_dict['key1']
existe, mas não é um dict (ou um objeto do tipo dict com umget
método). Otry..except
código que você postou aumentaria umaTypeError
vez seexample_dict['key1']
ser subscrito.Outra diferença é que os
try...except
curtos-circuitos imediatamente após a primeira tecla ausente. A cadeia deget
chamadas não.Se você deseja preservar a sintaxe,
example_dict['key1']['key2']
mas não deseja que ele aumente KeyErrors, use a receita Hasher :Observe que isso retorna um Hasher vazio quando uma chave está ausente.
Como
Hasher
é uma subclasse,dict
você pode usar um Hasher da mesma maneira que você poderia usar umdict
. Todos os mesmos métodos e sintaxe estão disponíveis, os Hashers tratam as chaves ausentes de maneira diferente.Você pode converter um regular
dict
em umHasher
assim:e converta a
Hasher
para regular comdict
a mesma facilidade:Outra alternativa é ocultar a feiura em uma função auxiliar:
Portanto, o restante do seu código pode ficar relativamente legível:
fonte
safeget
muitas maneiras, o método não é muito seguro, pois substitui o dicionário original, o que significa que você não pode fazer coisas como essassafeget(dct, 'a', 'b') or safeget(dct, 'a')
.safeget
nunca substitui o dicionário original. Ele retornará o dicionário original, um valor do dicionário original ouNone
.dct = dct[key]
reatribui um novo valor à variável localdct
. Isso não altera o ditado original (portanto, o ditado original não é afetadosafeget
.) Se, por outro lado,dct[key] = ...
tivesse sido usado, o ditado original teria sido modificado. Em outras palavras, em Python, os nomes estão vinculados a valores . Atribuição de um novo valor para um nome não afeta o valor antigo (a menos que não há mais referências ao valor antigo, caso em que (em CPython) ele irá obter lixo coletado.)Você também pode usar o python reduzir :
fonte
Ao combinar todas essas respostas aqui e as pequenas alterações que fiz, acho que essa função seria útil. é seguro, rápido e de fácil manutenção.
Exemplo:
fonte
deep_get({'a': 1}, "a.b")
dá,None
mas eu esperaria uma exceção comoKeyError
ou algo mais.None
paraRaise KeyError
Com base na resposta de Yoav, uma abordagem ainda mais segura:
fonte
Uma solução recursiva. Não é o mais eficiente, mas acho que é um pouco mais legível do que os outros exemplos e não depende de funções.
Exemplo
Uma versão mais polida
fonte
Embora a abordagem de redução seja organizada e curta, acho que um loop simples é mais fácil de criar. Eu também incluí um parâmetro padrão.
Como um exercício para entender como a redução de uma linha funcionava, fiz o seguinte. Mas, em última análise, a abordagem do loop parece mais intuitiva para mim.
Uso
fonte
Eu sugiro que você tente
python-benedict
.É um
dict
subclasse que fornece suporte ao caminho-chave e muito mais.Instalação:
pip install python-benedict
agora você pode acessar valores aninhados usando o caminho da chave :
ou acesse valores aninhados usando a lista de chaves :
É bem testado e de código aberto no GitHub :
https://github.com/fabiocaccamo/python-benedict
fonte
d.get('a.b[0].c[-1]')
Uma classe simples que pode agrupar um ditado e recuperar com base em uma chave:
Por exemplo:
Se a chave não existir, ela retornará
None
por padrão. Você pode substituir isso usando umadefault=
chave noFindDict
wrapper - por exemplo`:fonte
para uma recuperação de chave de segundo nível, você pode fazer o seguinte:
fonte
Depois de ver isso para obter atributos profundamente, fiz o seguinte para obter
dict
valores aninhados com segurança usando a notação de ponto. Isso funciona para mim porque meusdicts
objetos MongoDB são desserializados, então eu sei que os nomes das chaves não contêm.
s. Além disso, no meu contexto, posso especificar um valor de fallback falso (None
) que não possuo nos meus dados, para evitar o padrão try / except ao chamar a função.fonte
fallback
não é realmente usado na função.
sep=','
palavra - chave arg para generalizar para determinadas condições (sep, fallback). E @denvar, seobj
é o tipo de letraint
após uma sequência de redução, então obj [name] gera um TypeError, que eu pego. Se eu usasse obj.get (name) ou obj.get (name, fallback), isso geraria um AttributeError, então, de qualquer maneira, eu precisaria pegar.Ainda outra função para a mesma coisa, também retorna um booleano para representar se a chave foi encontrada ou não e lida com alguns erros inesperados.
exemplo de uso:
fonte
Você pode usar o pydash:
https://pydash.readthedocs.io/en/latest/api.html
fonte
Uma adaptação da resposta de unutbu que achei útil em meu próprio código:
Ele gera uma entrada de dicionário para key1 se ainda não tiver essa chave, para evitar o KeyError. Se você quiser acabar com um dicionário aninhado que inclua esse emparelhamento de teclas como eu fiz, essa parece ser a solução mais fácil.
fonte
Como gerar um erro de chave, se uma das chaves estiver faltando, é uma coisa razoável a se fazer, não podemos nem mesmo procurá-lo e torná-lo tão único quanto isso:
fonte
Pouca melhoria na
reduce
abordagem para fazê-la funcionar com a lista. Também usando o caminho de dados como sequência dividida por pontos em vez de matriz.fonte
Uma solução que eu usei é semelhante ao double get, mas com a capacidade adicional de evitar um TypeError usando a lógica if else:
No entanto, quanto mais aninhado o dicionário, mais complicado isso se torna.
fonte
Para pesquisas aninhadas de dicionário / JSON, você pode usar o dictor
dict de instalação do pip
objeto ditado
para obter os itens da Lonestar, basta fornecer um caminho separado por pontos, ou seja,
você pode fornecer um valor de fallback caso a chave não esteja no caminho
há muito mais opções que você pode fazer, como ignorar letras maiúsculas e minúsculas e usar outros caracteres além de '.' como um separador de caminho,
https://github.com/perfecto25/dictor
fonte
Eu pouco mudei esta resposta. Eu adicionei checando se estamos usando lista com números. Então agora podemos usá-lo de qualquer maneira.
deep_get(allTemp, [0], {})
oudeep_get(getMinimalTemp, [0, minimalTemperatureKey], 26)
etcfonte
Já existem muitas respostas boas, mas eu criei uma função chamada get similar to lodash get in JavaScript land, que também suporta acessar listas por índice:
fonte