Questa risposta è stata originariamente scritta in risposta a una domanda che è stata contrassegnata come duplicata:
Rimozione delle coordinate dall'elenco su Python
Esistono due problemi nel codice:
1) Quando si utilizza remove (), si tenta di rimuovere numeri interi mentre è necessario rimuovere una tupla.
2) Il ciclo for salterà gli elementi nell'elenco.
Esaminiamo cosa succede quando eseguiamo il tuo codice:
>>> 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)
Il primo problema è che stai passando 'a' e 'b' per rimuovere (), ma remove () accetta solo un singolo argomento. Quindi, come possiamo ottenere remove () per funzionare correttamente con il tuo elenco? Dobbiamo capire qual è ogni elemento del tuo elenco. In questo caso, ognuno è una tupla. Per vedere questo, accediamo a un elemento dell'elenco (l'indicizzazione inizia da 0):
>>> L1[1]
(5, 6)
>>> type(L1[1])
<type 'tuple'>
Aha! Ogni elemento di L1 è in realtà una tupla. Quindi è quello che dobbiamo passare per rimuovere (). Le tuple in pitone sono molto semplici, sono semplicemente create racchiudendo i valori tra parentesi. "a, b" non è una tupla, ma "(a, b)" è una tupla. Quindi modifichiamo il codice ed eseguiamo di nuovo:
# The remove line now includes an extra "()" to make a tuple out of "a,b"
L1.remove((a,b))
Questo codice viene eseguito senza errori, ma diamo un'occhiata all'elenco che genera:
L1 is now: [(1, 2), (5, 6), (1, -2)]
Perché (1, -2) è ancora nella tua lista? Si scopre che modificare l'elenco mentre si utilizza un ciclo per scorrere su di esso è una pessima idea senza cure particolari. Il motivo per cui (1, -2) rimane nell'elenco è che le posizioni di ciascun elemento all'interno dell'elenco sono cambiate tra le iterazioni del ciclo for. Diamo un'occhiata a cosa succede se alimentiamo il codice sopra un elenco più lungo:
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)]
Come puoi dedurre da quel risultato, ogni volta che l'istruzione condizionale viene valutata vera e viene rimosso un elemento dell'elenco, la successiva iterazione del ciclo salterà la valutazione dell'elemento successivo nell'elenco perché i suoi valori si trovano ora in indici diversi.
La soluzione più intuitiva è copiare l'elenco, quindi scorrere l'elenco originale e modificare solo la copia. Puoi provare a farlo in questo modo:
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)
Tuttavia, l'output sarà identico a prima:
'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]
Questo perché quando abbiamo creato L2, Python non ha effettivamente creato un nuovo oggetto. Invece, faceva semplicemente riferimento a L2 allo stesso oggetto di L1. Possiamo verificarlo con 'is' che è diverso dal semplice "uguale" (==).
>>> L2=L1
>>> L1 is L2
True
Possiamo fare una copia vera usando copy.copy (). Quindi tutto funziona come previsto:
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)]
Infine, esiste una soluzione più pulita rispetto alla necessità di creare una copia completamente nuova di L1. La funzione inversa ():
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)]
Sfortunatamente, non riesco a descrivere adeguatamente come funziona reverse (). Restituisce un oggetto 'listreverseiterator' quando gli viene passato un elenco. Ai fini pratici, puoi pensarlo come creare una copia rovesciata del suo argomento. Questa è la soluzione che raccomando.