thelist[:] = [d for d in thelist if d.get('id') != 2]
Editar: como algunas dudas se han expresado en un comentario acerca de la ejecución de este código (algunos basada en un malentendido características de rendimiento de Python, algunos en el supuesto más allá de las especificaciones, dado que hay exactamente un dict en el lista con un valor de 2 para la clave 'id'), deseo ofrecerle tranquilidad en este punto.
En un sistema Linux de edad, la medición de este código:
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(99)]; import random" "thelist=list(lod); random.shuffle(thelist); thelist[:] = [d for d in thelist if d.get('id') != 2]"
10000 loops, best of 3: 82.3 usec per loop
de los cuales unos 57 microsegundos para la random.shuffle (necesario para asegurar que el elemento a eliminar no está siempre en el mismo lugar ;-) y 0.65 microsegundos para la copia inicial (quienquiera que se preocupe por el impacto en el rendimiento de las copias superficiales de las listas de Python es obviamente fuera del almuerzo ;-), necesario para evitar alterar la lista original en el ciclo (para que cada tramo del ciclo tenga algo que borrar;-).
Cuando se sabe que hay exactamente un elemento para eliminarlo, es posible localizar y eliminar aún más expedita:
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(99)]; import random" "thelist=list(lod); random.shuffle(thelist); where=(i for i,d in enumerate(thelist) if d.get('id')==2).next(); del thelist[where]"
10000 loops, best of 3: 72.8 usec per loop
(utilice el next
incorporado en lugar del método .next
si estás en Python 2.6 o superior, por supuesto), pero este código se rompe si la cantidad de dictados que satisfacen la condición de eliminación no es exactamente uno. Generalizar esto, tenemos:
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(33)]*3; import random" "thelist=list(lod); where=[i for i,d in enumerate(thelist) if d.get('id')==2]; where.reverse()" "for i in where: del thelist[i]"
10000 loops, best of 3: 23.7 usec per loop
donde el barajado se puede quitar porque ya hay tres predice equidistantes a eliminar, tal como la conocemos. Y el listcomp, sin cambios, tarifas así:
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(33)]*3; import random" "thelist=list(lod); thelist[:] = [d for d in thelist if d.get('id') != 2]"
10000 loops, best of 3: 23.8 usec per loop
totalmente el cuello y el cuello, incluso con sólo 3 elementos de la 99 a ser eliminado. Con las listas más largas y más repeticiones, esto es aún más claro:
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(33)]*133; import random" "thelist=list(lod); where=[i for i,d in enumerate(thelist) if d.get('id')==2]; where.reverse()" "for i in where: del thelist[i]"
1000 loops, best of 3: 1.11 msec per loop
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(33)]*133; import random" "thelist=list(lod); thelist[:] = [d for d in thelist if d.get('id') != 2]"
1000 loops, best of 3: 998 usec per loop
Con todo, no es evidente que debemos desplegar la sutileza de decisiones y la inversión de la lista de índices de remover, frente a la lista muy simple y obvia comprensión, para ganar posiblemente 100 nanosegundos en un caso pequeño y perder 113 microsegundos en uno más grande ;-). Evitar o criticar soluciones simples, sencillas y perfectamente adecuadas para el desempeño (como listas de comprensión para esta clase general de problemas de "eliminar algunos elementos de una lista") es un ejemplo particularmente desagradable de la conocida tesis de Knuth y Hoare de que "la optimización prematura es la raíz de todos los males en la programación "-)
Dos razones por las que esto es malo: copia la lista completa, y recorre toda la lista incluso si el diccionario que contiene la identificación 2 es el primer elemento. – Imagist
@imagist, es sin embargo el más rápido - MEDIR, por el amor de Dios, no solo ASUMIR sabes de lo que estás hablando, esp. cuando obviamente no lo haces ;-), * ESPECIALMENTE * cuando el elemento a eliminar es el primero (evita mover cualquier otro elemento). Y no hay ninguna indicación en la pregunta original de que cada dict en la lista DEBE tener siempre un valor diferente que corresponda a 'id'. –
Hmmmm. No está mal. Hay dos enfoques: hacer una nueva lista con algunos elementos filtrados o modificar la lista existente para eliminar algunos elementos. Este es solo el primer enfoque. Y en la medida de lo posible, no hay nada que decir que un diccionario con id = 2 no aparecerá más de una vez en la lista. Es una lista; no hay garantía de exclusividad. Y el OP no sugirió esta limitación. – hughdbrown