Como remover uma chave de um dicionário Python?


Respostas:


2841

Para excluir uma chave, independentemente de ela estar no dicionário, use o formato de dois argumentos dict.pop():

my_dict.pop('key', None)

Isso retornará my_dict[key]se keyexistir no dicionário e Nonecaso contrário. Se o segundo parâmetro não for especificado (ou seja my_dict.pop('key')) e keynão existir, a KeyErrorserá gerado.

Para excluir uma chave com garantia de existência, você também pode usar

del my_dict['key']

Isso aumentará a KeyErrorse a chave não estiver no dicionário.


153
Às vezes, uma vantagem do uso pop()excessivo del: retorna o valor para essa chave. Dessa forma, você pode obter e excluir uma entrada de um ditado em uma linha de código.
precisa saber é o seguinte

7
Na pergunta, não é necessário manter o valor. Isso apenas adicionaria complexidade desnecessária. A resposta do @zigg (abaixo) é muito melhor.
Salvatore Cosentino

10
@SalvatoreCosentino Não posso seguir seu argumento. Como o código nesta resposta é mais complexo que o código na outra resposta?
Sven Marnach

33
@SalvatoreCosentino Não, ignorar o valor de retorno de uma função não é ineficiente. Muito pelo contrário - essa solução é muito mais rápida que a solução try/ exceptse a chave não existir. Você pode achar um ou outro mais fácil de ler, o que é bom. Ambos são Python idiomáticos, então escolha o que preferir. Mas afirmar que essa resposta é mais complexa ou ineficiente simplesmente não faz sentido.
Sven Marnach

5
@ user5359531 Eu não entendo. Como isso é um problema? Nenhum dos métodos nos tipos internos do Python retorna self, portanto, seria bastante surpreendente se esse acontecesse.
Sven Marnach 02/08/19

353

Especificamente para responder "existe uma maneira única de fazer isso?"

if 'key' in my_dict: del my_dict['key']

... bem, você perguntou ;-)

Você deve considerar, no entanto, que essa maneira de excluir um objeto de a nãodict é atômica - é possível que 'key'possa estar presente my_dictdurante a ifinstrução, mas pode ser excluída antes da delexecução, caso em que delfalhará com a KeyError. Diante disso, seria mais seguro usardict.pop ou algo do tipo:

try:
    del my_dict['key']
except KeyError:
    pass

o que, é claro, definitivamente não é uma linha.


27
Sim, popé definitivamente mais conciso, embora exista uma vantagem importante de fazê-lo desta maneira: fica imediatamente claro o que está fazendo.
zigg

4
A try/exceptafirmação é mais cara. Gerar uma exceção é lento.
Chris Barker

16
@ ChrisBarker, eu descobri que se a chave existe, tryé marginalmente mais rápida, embora, se não existir, tryé realmente muito mais lenta. popé razoavelmente consistente, mas mais lento que tudo, mas trycom uma chave não presente. Consulte gist.github.com/zigg/6280653 . Em última análise, depende de quantas vezes você espera que a chave para realmente estar no dicionário, e se ou não você precisa atomicity-e, é claro, se você está ou não se envolver em otimização prematura;)
zigg

9
Acredito que o valor da clareza não deve ser esquecido. +1 para isso.
Juan Carlos Coto

2
em relação à despesa de tentativa / exceção, você também pode ir if 'key' in mydict: #then del.... Eu precisava retirar uma chave / val de um ditado para analisar corretamente, o pop não era uma solução perfeita.
Marc

153

Levei algum tempo para descobrir o que exatamente my_dict.pop("key", None)está fazendo. Então, adicionarei isso como resposta para economizar tempo no Google:

pop(key[, default])

Se a chave estiver no dicionário, remova-a e retorne seu valor; caso contrário, retorne o padrão . Se o padrão não for fornecido e a chave não estiver no dicionário, a KeyErrorserá gerado.

Documentação


15
Basta digitar help (dict.pop) no interpretador python.
David Mulder

13
help () e dir () podem ser seus amigos quando você precisa saber o que algo faz.
David Mulder

3
ou dict.pop?no IPython.
precisa saber é o seguinte

51

del my_dict[key]é um pouco mais rápido do que my_dict.pop(key)para remover uma chave de um dicionário quando a chave existe

>>> import timeit
>>> setup = "d = {i: i for i in range(100000)}"

>>> timeit.timeit("del d[3]", setup=setup, number=1)
1.79e-06
>>> timeit.timeit("d.pop(3)", setup=setup, number=1)
2.09e-06
>>> timeit.timeit("d2 = {key: val for key, val in d.items() if key != 3}", setup=setup, number=1)
0.00786

Mas quando a chave não existe, if key in my_dict: del my_dict[key]é um pouco mais rápido que my_dict.pop(key, None). Ambos são pelo menos três vezes mais rápidos do que delem uma declaração try/ except:

>>> timeit.timeit("if 'missing key' in d: del d['missing key']", setup=setup)
0.0229
>>> timeit.timeit("d.pop('missing key', None)", setup=setup)
0.0426
>>> try_except = """
... try:
...     del d['missing key']
... except KeyError:
...     pass
... """
>>> timeit.timeit(try_except, setup=setup)
0.133

1
Medir o tempo de uma operação tão rápida é bastante estúpido. Seu código provavelmente não ficará muito mais rápido porque você alterou de a poppara a del. A criação do dicionário anula completamente as coisas dele.
Boris

1
@ Boris - isso é útil como um exercício geral.
daisy

1
@daisy o que estou dizendo é que você deve escolher a sintaxe mais legível, não a operação que é 300 nanossegundos mais rápida (que é literalmente a diferença entre dele popdesde o primeiro conjunto de horários acima)
Boris

Além disso, essas operações são tão rápidas que esses tempos não são confiáveis.
Boris

46

Se você precisar remover muitas chaves de um dicionário em uma linha de código, acho que usar map () é bastante sucinto e legível por Python:

myDict = {'a':1,'b':2,'c':3,'d':4}
map(myDict.pop, ['a','c']) # The list of keys to remove
>>> myDict
{'b': 2, 'd': 4}

E se você precisar capturar erros nos quais você insere um valor que não está no dicionário, use lambda dentro de map () assim:

map(lambda x: myDict.pop(x,None), ['a', 'c', 'e'])
[1, 3, None] # pop returns
>>> myDict
{'b': 2, 'd': 4}

ou python3, você deve usar uma compreensão da lista:

[myDict.pop(x, None) for x in ['a', 'c', 'e']]

Funciona. E 'e' não causou um erro, mesmo que o myDict não tenha uma chave 'e'.


42
Isso não funcionará no Python 3 porque os mapamigos agora são preguiçosos e retornam iteradores. Usar mapefeitos colaterais geralmente é considerado uma má prática; um for ... inloop padrão seria melhor. Consulte Exibições e iteradores em vez de listas para obter mais informações.
precisa saber é o seguinte

5
Independentemente do gosto e do estilo da prática, a compreensão da lista ainda deve funcionar no Py3 [myDict.pop(i, None) for i in ['a', 'c']], pois oferece uma alternativa geral a map(e filter).
Michael Ekoka

@ MichaelEkoka, você não deve usar a compreensão de lista para seus efeitos colaterais, use um for ... inloop regular .
Boris

@ Boris Você provavelmente está certo. Minha resposta diz respeito especificamente ao uso map(), que costuma ser usado por seus efeitos colaterais. A alternativa recomendada no Python é a compreensão da lista, que, na minha opinião, ainda é bastante legível e cognitivamente leve como uma linha (veja a pergunta). Utilizadas apenas pelos efeitos colaterais, ambas as construções resultam em uma lista inútil, que pode ser ineficiente. No Python3, não conheço uma função interna que possa iterar com segurança e elegância através de uma expressão de gerador, sem um subproduto caro, por exemplo loop(d.pop(k) for k in ['a', 'b']).
Michael Ekoka

Estou divertido que minha resposta mais votada de todos os tempos inclua alguns hacks que eu nunca usaria. A compreensão da lista (opção 3) é a abordagem menos ruim, na minha opinião. Use esse.
Marc Maxmeister

20

Você pode usar uma compreensão de dicionário para criar um novo dicionário com essa chave removida:

>>> my_dict = {k: v for k, v in my_dict.items() if k != 'key'}

Você pode excluir por condições. Nenhum erro se keynão existir.



7

Podemos excluir uma chave de um dicionário Python pelas seguintes abordagens.

Usando a delpalavra - chave; é quase a mesma abordagem que você fez -

 myDict = {'one': 100, 'two': 200, 'three': 300 }
 print(myDict)  # {'one': 100, 'two': 200, 'three': 300}
 if myDict.get('one') : del myDict['one']
 print(myDict)  # {'two': 200, 'three': 300}

Ou

Podemos fazer o seguinte:

Mas é preciso ter em mente que, nesse processo, na verdade, ele não excluirá nenhuma chave do dicionário, em vez de excluir a chave específica desse dicionário. Além disso, observei que ele retornava um dicionário que não tinha o mesmo pedido de myDict.

myDict = {'one': 100, 'two': 200, 'three': 300, 'four': 400, 'five': 500}
{key:value for key, value in myDict.items() if key != 'one'}

Se o rodarmos no shell, ele executará algo como {'five': 500, 'four': 400, 'three': 300, 'two': 200}- observe que não é o mesmo pedido que myDict. Novamente, se tentarmos imprimir myDict, podemos ver todas as chaves, incluindo as que foram excluídas do dicionário por essa abordagem. No entanto, podemos criar um novo dicionário atribuindo a seguinte instrução a uma variável:

var = {key:value for key, value in myDict.items() if key != 'one'}

Agora, se tentarmos imprimi-lo, seguirá a ordem dos pais:

print(var) # {'two': 200, 'three': 300, 'four': 400, 'five': 500}

Ou

Usando o pop()método

myDict = {'one': 100, 'two': 200, 'three': 300}
print(myDict)

if myDict.get('one') : myDict.pop('one')
print(myDict)  # {'two': 200, 'three': 300}

A diferença entre dele popé que, usando o pop()método, podemos realmente armazenar o valor da chave, se necessário, como o seguinte:

myDict = {'one': 100, 'two': 200, 'three': 300}
if myDict.get('one') : var = myDict.pop('one')
print(myDict) # {'two': 200, 'three': 300}
print(var)    # 100

Bifurque esta essência para referência futura, se você achar isso útil.


1
Não use if myDict.get('one')para verificar se uma chave está presente! Falha se myDict ['one'] tiver um valor de falsey. Além disso, os ditados não têm uma ordem inerente, portanto, não faz sentido mencioná-la.
28419 Rob

Os dicionários do @Rob são ordenados por ordem de inserção começando no CPython 3.6 e em todas as outras implementações do Python começando no 3.7.
Boris

4

Você pode usar o tratamento de exceções se quiser ser muito detalhado:

try: 
    del dict[key]

except KeyError: pass

Isso é mais lento, porém, que o pop()método, se a chave não existir.

my_dict.pop('key', None)

Não importa para algumas chaves, mas se você estiver fazendo isso repetidamente, o último método será uma aposta melhor.

A abordagem mais rápida é a seguinte:

if 'key' in dict: 
    del myDict['key']

Mas esse método é perigoso porque se 'key'for removido entre as duas linhas, a KeyErrorserá gerado.


1

Eu prefiro a versão imutável

foo = {
    1:1,
    2:2,
    3:3
}
removeKeys = [1,2]
def woKeys(dct, keyIter):
    return {
        k:v
        for k,v in dct.items() if k not in keyIter
    }

>>> print(woKeys(foo, removeKeys))
{3: 3}
>>> print(foo)
{1: 1, 2: 2, 3: 3}

1

Outra maneira é usar a compreensão de itens () + dict

items () juntamente com a compreensão de ditado também pode nos ajudar a realizar a tarefa de exclusão do par de valores-chave, mas tem a desvantagem de não ser uma técnica de ditado local. Na verdade, um novo ditado se criado, exceto a chave que não queremos incluir.

test_dict = {"sai" : 22, "kiran" : 21, "vinod" : 21, "sangam" : 21} 

# Printing dictionary before removal 
print ("dictionary before performing remove is : " + str(test_dict)) 

# Using items() + dict comprehension to remove a dict. pair 
# removes  vinod
new_dict = {key:val for key, val in test_dict.items() if key != 'vinod'} 

# Printing dictionary after removal 
print ("dictionary after remove is : " + str(new_dict)) 

Resultado:

dictionary before performing remove is : {'sai': 22, 'kiran': 21, 'vinod': 21, 'sangam': 21}
dictionary after remove is : {'sai': 22, 'kiran': 21, 'sangam': 21}

0

Filtro único na chave

  • retorne "key" e remova-o de my_dict se "key" existir em my_dict
  • return None se "key" não existir em my_dict

isso mudará my_dictde lugar (mutável)

my_dict.pop('key', None)

Vários filtros nas teclas

gerar um novo ditado (imutável)

dic1 = {
    "x":1,
    "y": 2,
    "z": 3
}

def func1(item):
    return  item[0]!= "x" and item[0] != "y"

print(
    dict(
        filter(
            lambda item: item[0] != "x" and item[0] != "y", 
            dic1.items()
            )
    )
)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.