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

2282

Al eliminar una clave de un diccionario, uso:

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

¿Hay alguna forma de hacer esto en una línea?

2
3686

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 volverá 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 cuya existencia está garantizada, también puede utilizar:

del my_dict['key']

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

12
  • 208
    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 dictado en una línea de código. 18 de agosto de 2013 a las 12:21
  • 7
    En la pregunta no es necesario mantener el valor. Esto solo agregaría una complejidad innecesaria. La respuesta de @zigg (abajo) es mucho mejor. 14 de junio de 2017 a las 2:05
  • 14
    @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? 15 de junio de 2017 a las 13:52
  • 46
    @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. Puede encontrar uno u otro más fácil de leer, lo cual está bien. Ambos son Python idiomáticos, así que elija lo que prefiera. Pero afirmar que esta respuesta es más compleja o ineficiente simplemente no tiene sentido. 15 de junio de 2017 a las 18:44
  • 6
    @ user5359531 No entiendo. ¿Cómo es esto un problema? Ninguno de los métodos de los tipos integrados de Python devuelve self, por lo que sería bastante sorprendente que este lo hiciera. 2 de agosto de 2018 a las 10:09
404

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

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

... bueno, preguntaste ;-)

Sin embargo, debe considerar que esta forma de eliminar un objeto de a nodict es atómica ; es posible que 'key'esté my_dictdurante la ifinstrucción, pero puede eliminarse antes de que delse ejecute, en cuyo caso delfallará con a KeyError. Dado esto, sería más seguro usardict.pop o algo similar a

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

que, por supuesto, definitivamente no es una frase de una sola línea.

10
  • 32
    Sí, popes definitivamente más conciso, aunque hay una ventaja clave de hacerlo de esta manera: es inmediatamente claro lo que está haciendo.
    zigg
    1 de julio de 2012 a las 16:30
  • 6
    La try/exceptdeclaración es más cara. Generar una excepción es lento. 20/0813 a las 5:01
  • 18
    @ChrisBarker He descubierto que si la clave existe, tryes un poco 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. Consulta gist.github.com/zigg/6280653 . En última instancia, depende de la frecuencia con la que espera que la clave esté realmente en el diccionario y de si necesita o no atomicidad y, por supuesto, de si está realizando una optimización prematura o no;)
    zigg
    20/0813 a las 12:18
  • 10
    Creo que el valor de la claridad no debe pasarse por alto. +1 para esto. 30/06/2014 a las 21:15
  • 3
    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 dictado para analizar correctamente, pop no era una solución perfecta.
    Marc
    9 de julio de 2015 a las 18:00
174

Me tomó un tiempo averiguar qué estaba my_dict.pop("key", None)haciendo exactamente . Así que agregaré esto como una respuesta para ahorrarles tiempo a otras personas que buscan en Google:

pop(key[, default])

If key is in the dictionary, remove it and return its value, else return default. If default is not given and key is not in the dictionary, a KeyError is raised.

Documentación

3
  • 21
    Simplemente escriba help (dict.pop) en el intérprete de Python. 6 de agosto de 2013 a las 18:07
  • dieciséis
    help () y dir () pueden ser tus amigos cuando necesites saber qué hace algo. 6 de agosto de 2013 a las 18:08
  • 4
    o dict.pop?en IPython. 13/04/14 a las 1:09
69

del my_dict[key]es un poco más rápido que my_dict.pop(key)eliminar una clave de un diccionario cuando la clave 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

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
3
  • 4
    @Boris: esto es útil como ejercicio general.
    K--
    6 abr.20 a las 22:12
  • 3
    @daisy, lo que estoy diciendo es que debe elegir la sintaxis más legible, no la operación que es 300 nanosegundos más rápida (esa es literalmente la diferencia entre dely popdesde el primer conjunto de tiempos anterior)
    Boris
    6 abr.20 a las 22:33
  • Además, estas operaciones son tan rápidas que estos tiempos no son confiables.
    Boris
    6 abr.20 a las 22:47
60

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

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 en los que 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, debe 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, aunque myDict no tenía una clave 'e'.

7
  • 43
    Esto no funcionará en Python 3 porque los mapamigos ahora son perezosos y devuelven iteradores. El uso mappara 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. 7/11/15 a las 16:31
  • 5
    Independientemente del gusto y el estilo de práctica, las listas por comprensió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). 22/10/2017 a las 8:48
  • 1
    @MichaelEkoka, no debes usar listas de comprensión por sus efectos secundarios, usa un for ... inciclo regular .
    Boris
    3 abr.20 a las 8:32
  • @Boris Probablemente tengas razón. Mi respuesta es específicamente relacionada con el 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 ligera como una sola línea (ver pregunta). Usados ​​solo por sus efectos secundarios, ambos constructos de hecho dan como resultado una lista inútil, que puede ser ineficaz. 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 generadora, sin un subproducto costoso, por ejemplo loop(d.pop(k) for k in ['a', 'b']). 7 abr.20 a las 14:06
  • 1
    @MichaelEkoka la "orden interna función" es un bucle for: for k in ['a', 'b']: d.pop(k). ¿Por qué necesitas una forma diferente de hacerlo? Si necesita que ocupe tan solo una línea, puede poner la segunda parte del bucle for en la misma línea.
    Boris
    4 de mayo de 2020 a las 14:18
40

Puede utilizar la comprensión de un diccionario para crear un nuevo diccionario sin esa clave:

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

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

2
  • Esta respuesta es diferente a las demás porque no tiene efectos secundarios (no modifica el diccionario original). 5 de agosto de 2020 a las 23:33
  • 2
    Si bien esta es probablemente la forma en que lo haría también, esto crea un diccionario completamente nuevo en la memoria, copiando (referencias a) objetos en el nuevo diccionario. Luego lo guarda en el nombre anterior. En el caso de diccionarios grandes, esto puede llevar algún tiempo. del dict[key]o dict.pop(key)será más rápido en todos los casos.
    mazunki
    20/11/20 a las 19:51
18

Usando la palabra clave "del":

del dict[key]
0
8

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)

No importará para algunas teclas, pero si lo hace repetidamente, entonces el último método es una mejor apuesta.

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 KeyErrorgenerará a.

8

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

Usando la delpalabra clave; Sin embargo, 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 devolvía 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, ejecutará algo como {'five': 500, 'four': 400, 'three': 300, 'two': 200}: observe que no tiene el mismo orden que myDict. Nuevamente, si intentamos imprimir myDict, podemos ver todas las claves, incluidas las que excluimos del diccionario con este enfoque. Sin embargo, podemos crear un nuevo diccionario asignando la siguiente declaración a una variable:

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

Ahora, si intentamos 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 se muestra a continuación:

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 esencia para referencia futura, si lo encuentra útil.

2
  • 6
    ¡No lo utilice if myDict.get('one')para comprobar si hay una llave! Falla si myDict ['one'] tiene un valor falso. Además, los dictados no tienen un orden inherente, por lo que no tiene sentido mencionarlos.
    Rob
    28 feb 2019 a las 8:35
  • Los dictados de @Rob se ordenan por orden de inserción comenzando con CPython 3.6 y todas las demás implementaciones de Python comenzando con 3.7.
    Boris
    3 abr.20 a las 8:29
5

El tipo de datos de diccionario tiene un método llamado dict_name.pop(item)y se puede utilizar para eliminar un par clave: valor de un diccionario.

a={9:4,2:3,4:2,1:3}
a.pop(9)
print(a)

Esto dará la salida como:

{2: 3, 4: 2, 1: 3}

De esta forma, puede eliminar un elemento de un diccionario en una línea.

4

Otra forma es usando ítems () + comprensión de dic.

items () junto con la comprensión de dict también pueden ayudarnos a lograr la tarea de eliminación del par clave-valor, pero tiene el inconveniente de no ser una técnica de dict en su lugar. En realidad, se crea un nuevo dictado excepto por 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))

Producción:

dictionary before performing remove is : {'sai': 22, 'kiran': 21, 'vinod': 21, 'sangam': 21}
dictionary after remove is : {'sai': 22, 'kiran': 21, 'sangam': 21}
1
  • esto en realidad no hace lo que se pide, crea un nuevo dictado con las claves no deseadas eliminadas. Además, iterar sobre todas las claves para eliminar una es realizar una operación O (1) en tiempo O (N).
    anon01
    4 de mayo a las 22:20
3

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

Filtro único en clave

  • devolver "clave" y eliminarlo de my_dict si "clave" existe en my_dict
  • devuelve Ninguno si la "clave" no existe en my_dict

this will change my_dict in place (mutable)

my_dict.pop('key', None)

Múltiples filtros en claves

generate a new dict (immutable)

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