Esta respuesta se escribió originalmente en respuesta a una pregunta que desde entonces se ha marcado como duplicada:
Eliminar coordenadas de la lista en Python
Hay dos problemas en su código:
1) Cuando usa remove (), intenta eliminar enteros mientras que necesita eliminar una tupla.
2) El bucle for omitirá elementos en su lista.
Repasemos lo que sucede cuando ejecutamos su código:
>>> L1 = [(1,2), (5,6), (-1,-2), (1,-2)]
>>> for (a,b) in L1:
... if a < 0 or b < 0:
... L1.remove(a,b)
...
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
TypeError: remove() takes exactly one argument (2 given)
El primer problema es que está pasando 'a' y 'b' para eliminar (), pero remove () solo acepta un único argumento. Entonces, ¿cómo podemos hacer que remove () funcione correctamente con su lista? Necesitamos descubrir cuál es cada elemento de su lista. En este caso, cada uno es una tupla. Para ver esto, accedamos a un elemento de la lista (la indexación comienza en 0):
>>> L1[1]
(5, 6)
>>> type(L1[1])
<type 'tuple'>
¡Ajá! Cada elemento de L1 es en realidad una tupla. Entonces eso es lo que debemos pasar para eliminar (). Las tuplas en python son muy fáciles, simplemente se hacen encerrando valores entre paréntesis. "a, b" no es una tupla, pero "(a, b)" es una tupla. Entonces modificamos su código y lo ejecutamos nuevamente:
# The remove line now includes an extra "()" to make a tuple out of "a,b"
L1.remove((a,b))
Este código se ejecuta sin ningún error, pero veamos la lista que muestra:
L1 is now: [(1, 2), (5, 6), (1, -2)]
¿Por qué (1, -2) todavía está en su lista? Resulta que modificar la lista mientras se usa un bucle para iterar es una muy mala idea sin un cuidado especial. La razón por la que (1, -2) permanece en la lista es que las ubicaciones de cada elemento dentro de la lista cambiaron entre iteraciones del bucle for. Veamos qué sucede si le damos al código anterior una lista más larga:
L1 = [(1,2),(5,6),(-1,-2),(1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
### Outputs:
L1 is now: [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]
Como puede deducir de ese resultado, cada vez que la declaración condicional se evalúa como verdadera y se elimina un elemento de la lista, la siguiente iteración del bucle omitirá la evaluación del siguiente elemento de la lista porque sus valores ahora se encuentran en diferentes índices.
La solución más intuitiva es copiar la lista, luego iterar sobre la lista original y solo modificar la copia. Puedes intentar hacerlo así:
L2 = L1
for (a,b) in L1:
if a < 0 or b < 0 :
L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
print L2 is L1
del L1
L1 = L2; del L2
print ("L1 is now: ", L1)
Sin embargo, la salida será idéntica a la anterior:
'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]
Esto se debe a que cuando creamos L2, python en realidad no creó un nuevo objeto. En cambio, simplemente hizo referencia a L2 al mismo objeto que L1. Podemos verificar esto con 'is', que es diferente de simplemente "igual" (==).
>>> L2=L1
>>> L1 is L2
True
Podemos hacer una copia verdadera usando copy.copy (). Entonces todo funciona como se esperaba:
import copy
L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
L2 = copy.copy(L1)
for (a,b) in L1:
if a < 0 or b < 0 :
L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
del L1
L1 = L2; del L2
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]
Finalmente, hay una solución más limpia que tener que hacer una copia completamente nueva de L1. La función invertida ():
L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
for (a,b) in reversed(L1):
if a < 0 or b < 0 :
L1.remove((a,b))
print ("L1 is now: ", L1)
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]
Desafortunadamente, no puedo describir adecuadamente cómo funciona reverse (). Devuelve un objeto 'listreverseiterator' cuando se le pasa una lista. Para fines prácticos, puede pensar que se trata de una copia inversa de su argumento. Esta es la solución que recomiendo.