¿Cómo eliminar una clave de un diccionario de Python?

Respuestas:

2843

Para eliminar una clave independientemente de si está en el diccionario, use la forma de dos argumentos de dict.pop():

my_dict.pop('key', None)

Esto regresará my_dict[key]si keyexiste en el diccionario, y de lo Nonecontrario. Si el segundo parámetro no se especifica (es decir my_dict.pop('key')) y keyno existe, KeyErrorse genera a.

Para eliminar una clave que se garantiza que existe, también puede usar

del my_dict['key']

Esto elevará un KeyErrorsi la clave no está en el diccionario.

Sven Marnach
fuente
153
A veces, una ventaja de usar pop()over del: devuelve el valor de esa clave. De esta manera, puede obtener y eliminar una entrada de un dict en una línea de código.
kratenko
77
En la pregunta no es necesario mantener el valor. Esto solo agregaría una complejidad innecesaria. La respuesta de @zigg (abajo) es mucho mejor.
Salvatore Cosentino
10
@SalvatoreCosentino No puedo seguir tu argumento. ¿Cómo es el código en esta respuesta más complejo que el código en la otra respuesta?
Sven Marnach
33
@SalvatoreCosentino No, ignorar el valor de retorno de una función no es ineficiente en absoluto. Todo lo contrario: esta solución es mucho más rápida que la solución try/ exceptsi la clave no existe. Es posible que encuentre uno u otro más fácil de leer, lo cual está bien. Ambos son Python idiomáticos, así que elige lo que prefieras. Pero afirmar que esta respuesta es más compleja o ineficiente simplemente no tiene sentido.
Sven Marnach
55
@ user5359531 No entiendo. ¿Cómo es esto un problema? Ninguno de los métodos en los tipos incorporados de Python devuelve self, por lo que sería bastante sorprendente si este lo hiciera.
Sven Marnach
353

Específicamente para responder "¿hay una forma de hacer esto en una línea?"

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

... bueno, preguntaste ;-)

Sin embargo, debe tener en cuenta que esta forma de eliminar un objeto de a nodict es atómica: es posible que 'key'se encuentre my_dictdurante la ifinstrucción, pero que se elimine antes de delejecutarse, en cuyo caso delfallará con a KeyError. Dado esto, sería más seguro usardict.pop o algo similar a las líneas de

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

que, por supuesto, definitivamente no es una frase.

zigg
fuente
27
Sí, popes definitivamente más conciso, aunque hay una ventaja clave de hacerlo de esta manera: está claro de inmediato lo que está haciendo.
zigg
44
La try/exceptdeclaración es más cara. Elevar una excepción es lento.
Chris Barker
16
@ChrisBarker He encontrado que si la clave existe, tryes marginalmente más rápida, aunque si no es así, tryes mucho más lenta. popes bastante consistente pero más lento que todos pero trycon una clave no presente. Ver gist.github.com/zigg/6280653 . En última instancia, depende de la frecuencia con la que espere que la clave esté realmente en el diccionario y de si necesita o no atomicidad, y, por supuesto, de si está participando o no en una optimización prematura;)
zigg
99
Creo que el valor de la claridad no debe pasarse por alto. +1 por esto.
Juan Carlos Coto
2
con respecto a los gastos de prueba / excepto, también puede ir if 'key' in mydict: #then del.... Necesitaba sacar una clave / val de un dict para analizar correctamente, pop no era una solución perfecta.
Marc
153

Me tomó un tiempo descubrir qué my_dict.pop("key", None)es exactamente lo que está haciendo. Entonces agregaré esto como una respuesta para ahorrar tiempo a otros en Google:

pop(key[, default])

Si la clave está en el diccionario, elimínela y devuelva su valor; de lo contrario, devuelva el valor predeterminado . Si no se proporciona el valor predeterminado y la clave no está en el diccionario, KeyErrorse eleva a.

Documentación

Akavall
fuente
15
Simplemente escriba help (dict.pop) en el intérprete de python.
David Mulder
13
help () y dir () pueden ser tus amigos cuando necesites saber qué hace algo.
David Mulder
3
o dict.pop?en IPython.
Erik Kaplun
51

del my_dict[key]es ligeramente más rápido que my_dict.pop(key)para eliminar una clave de un diccionario cuando existe la clave

>>> 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

Pero cuando la clave no existe if key in my_dict: del my_dict[key]es un poco más rápido que my_dict.pop(key, None). Ambos son al menos tres veces más rápidos que delen una declaración 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
Peter Smit
fuente
1
Medir los tiempos de una operación tan rápida es bastante estúpido. Probablemente su código no vaya a ser mucho más rápido porque cambió popa a del. La creación del diccionario borrará por completo las cosas borradas de él.
Boris
1
@ Boris: esto es útil como ejercicio general.
Margarita
1
@daisy, lo que digo es que debes elegir la sintaxis más legible, no la operación que es 300 nanosegundos más rápido (esa es literalmente la diferencia entre dely popdesde el primer conjunto de temporizaciones anterior)
Boris
Además, estas operaciones son tan rápidas que estos tiempos no son confiables.
Boris
46

Si necesita eliminar muchas claves de un diccionario en una línea de código, creo que usar map () es bastante sucinto y legible por Pythonic:

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}

Y si necesita detectar errores donde aparece un valor que no está en el diccionario, use lambda dentro de map () de esta manera:

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

o en python3, debes usar una lista de comprensión en su lugar:

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

Funciona. Y 'e' no causó un error, a pesar de que myDict no tenía una clave 'e'.

Marc Maxmeister
fuente
42
Esto no funcionará en Python 3 porque los mapamigos ahora son flojos y devuelven iteradores. El uso mapde efectos secundarios generalmente se considera una mala práctica; un for ... inbucle estándar sería mejor. Consulte Vistas e iteradores en lugar de listas para obtener más información.
Greg Krimer
55
Independientemente del gusto y el estilo de práctica, las comprensiones de listas aún deberían funcionar en Py3 [myDict.pop(i, None) for i in ['a', 'c']], ya que ofrecen una alternativa general a map(y filter).
Michael Ekoka
@MichaelEkoka no deberías usar listas de comprensión para sus efectos secundarios, usa un for ... inciclo regular .
Boris
@ Boris Probablemente tengas razón. Mi respuesta se refiere específicamente al uso map(), que a menudo se usa por sus efectos secundarios. La alternativa recomendada en Python es la comprensión de la lista, que en mi opinión todavía es bastante legible y cognitivamente liviana como una frase (ver pregunta). Utilizados solo por sus efectos secundarios, ambas construcciones resultan en una lista inútil, que puede ser ineficiente. A partir de Python3, no conozco una función incorporada que pueda iterar de manera segura y elegante a través de una expresión de generador, sin un subproducto costoso, por ejemplo loop(d.pop(k) for k in ['a', 'b']).
Michael Ekoka
Me divierte saber que mi respuesta más votada de todos los tiempos incluye algunos trucos que nunca usaría. La comprensión de la lista (opción 3) es el enfoque menos malo, en mi opinión. Usa ese.
Marc Maxmeister
20

Puede usar una comprensión del diccionario para crear un nuevo diccionario con esa clave eliminada:

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

Puedes eliminar por condiciones. No hay error si keyno existe.

Shameem
fuente
13

Usando la palabra clave "del":

del dict[key]
Sarthak Gupta
fuente
7

Podemos eliminar una clave de un diccionario de Python mediante los siguientes enfoques.

Usando la delpalabra clave; aunque es casi el mismo enfoque que tú.

 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}

O

Podemos hacer lo siguiente:

Pero uno debe tener en cuenta que, en este proceso, en realidad no eliminará ninguna clave del diccionario en lugar de excluir una clave específica de ese diccionario. Además, observé que devolvió un diccionario que no estaba ordenado igual que myDict.

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

Si lo ejecutamos en el shell, se ejecutará algo así como {'five': 500, 'four': 400, 'three': 300, 'two': 200}: observe que no está ordenado de la misma manera que myDict. Nuevamente, si tratamos de imprimir myDict, podemos ver todas las claves, incluidas las que excluimos del diccionario mediante este enfoque. Sin embargo, podemos hacer un nuevo diccionario asignando la siguiente declaración en una variable:

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

Ahora, si tratamos de imprimirlo, seguirá el orden principal:

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

O

Usando el 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}

La diferencia entre dely popes que, usando el pop()método, podemos almacenar el valor de la clave si es necesario, como lo siguiente:

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

Bifurca esta esencia para referencia futura, si encuentras esto útil.

iNet
fuente
1
¡No lo use if myDict.get('one')para verificar si hay una llave presente! Falla si myDict ['one'] tiene un valor falso. Además, los dictos no tienen un orden inherente, por lo que no tiene sentido mencionarlo.
Rob
Los dictados de @Rob se ordenan por orden de inserción a partir de CPython 3.6 y todas las demás implementaciones de Python a partir de 3.7.
Boris
4

Puede usar el manejo de excepciones si desea ser muy detallado:

try: 
    del dict[key]

except KeyError: pass

Sin embargo, esto es más lento que el pop()método, si la clave no existe.

my_dict.pop('key', None)

Para algunas teclas no importará, pero si lo hace repetidamente, entonces el último método es una mejor opción.

El enfoque más rápido es este:

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

Pero este método es peligroso porque si 'key'se elimina entre las dos líneas, se KeyErrorelevará a.

Alec Alameddine
fuente
1

Prefiero la versión inmutable

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}
CervEd
fuente
1

Otra forma es mediante el uso de elementos () + comprensión dict

items () junto con la comprensión de dict también pueden ayudarnos a lograr la tarea de eliminación de pares clave-valor, pero tiene el inconveniente de no ser una técnica de dict in situ. En realidad, se crea un nuevo dict, excepto la clave que no deseamos 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)) 

Salida:

dictionary before performing remove is : {'sai': 22, 'kiran': 21, 'vinod': 21, 'sangam': 21}
dictionary after remove is : {'sai': 22, 'kiran': 21, 'sangam': 21}
Sai Kiran Sangam
fuente
0

Filtro único en llave

  • devolver "clave" y eliminarlo de my_dict si existe "clave" en my_dict
  • return None si "clave" no existe en my_dict

esto cambiará my_dicten su lugar (mutable)

my_dict.pop('key', None)

Múltiples filtros en llaves

generar un nuevo dict (inmutable)

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()
            )
    )
)
ZenG
fuente