Cette réponse a été écrite à l'origine en réponse à une question qui a depuis été marquée comme doublon:
Suppression des coordonnées de la liste sur python
Il y a deux problèmes dans votre code:
1) Lorsque vous utilisez remove (), vous essayez de supprimer des entiers alors que vous devez supprimer un tuple.
2) La boucle for sautera les éléments de votre liste.
Voyons ce qui se passe lorsque nous exécutons votre code:
>>> 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)
Le premier problème est que vous passez à la fois 'a' et 'b' à remove (), mais remove () n'accepte qu'un seul argument. Alors, comment pouvons-nous obtenir remove () pour fonctionner correctement avec votre liste? Nous devons déterminer quel est chaque élément de votre liste. Dans ce cas, chacun est un tuple. Pour voir cela, accédons à un élément de la liste (l'indexation commence à 0):
>>> L1[1]
(5, 6)
>>> type(L1[1])
<type 'tuple'>
Ah! Chaque élément de L1 est en fait un tuple. C'est donc ce que nous devons passer pour supprimer (). Les tuples en python sont très faciles, ils sont simplement créés en mettant des valeurs entre parenthèses. "a, b" n'est pas un tuple, mais "(a, b)" est un tuple. Nous modifions donc votre code et le réexécutons:
# The remove line now includes an extra "()" to make a tuple out of "a,b"
L1.remove((a,b))
Ce code s'exécute sans aucune erreur, mais regardons la liste qu'il génère:
L1 is now: [(1, 2), (5, 6), (1, -2)]
Pourquoi (1, -2) est-il toujours dans votre liste? Il s'avère que modifier la liste tout en utilisant une boucle pour itérer dessus est une très mauvaise idée sans soin particulier. La raison pour laquelle (1, -2) reste dans la liste est que les emplacements de chaque élément de la liste ont changé entre les itérations de la boucle for. Voyons ce qui se passe si nous alimentons le code ci-dessus une liste plus longue:
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)]
Comme vous pouvez le déduire de ce résultat, chaque fois que l'instruction conditionnelle prend la valeur true et qu'un élément de liste est supprimé, l'itération suivante de la boucle ignore l'évaluation de l'élément suivant dans la liste car ses valeurs sont désormais situées à différents indices.
La solution la plus intuitive consiste à copier la liste, puis à parcourir la liste d'origine et à modifier uniquement la copie. Vous pouvez essayer de le faire comme ceci:
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)
Cependant, la sortie sera identique à celle d'avant:
'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]
En effet, lorsque nous avons créé L2, python n'a pas réellement créé un nouvel objet. Au lieu de cela, il a simplement référencé L2 au même objet que L1. Nous pouvons vérifier cela avec 'is' qui est différent de simplement "égal" (==).
>>> L2=L1
>>> L1 is L2
True
Nous pouvons faire une vraie copie en utilisant copy.copy (). Ensuite, tout fonctionne comme prévu:
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)]
Enfin, il existe une solution plus propre que de faire une copie entièrement nouvelle de L1. La fonction reverse ():
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)]
Malheureusement, je ne peux pas décrire correctement le fonctionnement de reverse (). Il renvoie un objet 'listreverseiterator' lorsqu'une liste lui est transmise. Pour des raisons pratiques, vous pouvez le considérer comme créant une copie inversée de son argument. C'est la solution que je recommande.