Ta odpowiedź została pierwotnie napisana w odpowiedzi na pytanie, które zostało oznaczone jako duplikat:
Usuwanie współrzędnych z listy w pythonie
W twoim kodzie są dwa problemy:
1) Korzystając z funkcji remove (), próbujesz usunąć liczby całkowite, ale musisz usunąć krotkę.
2) Pętla for spowoduje pominięcie pozycji na liście.
Zobaczmy, co się stanie, gdy wykonamy Twój kod:
>>> 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)
Pierwszy problem polega na tym, że przekazujesz zarówno „a”, jak i „b” do remove (), ale remove () akceptuje tylko jeden argument. Jak więc możemy usunąć remove (), aby działał poprawnie z twoją listą? Musimy dowiedzieć się, jaki jest każdy element twojej listy. W tym przypadku każdy jest krotką. Aby to zobaczyć, uzyskajmy dostęp do jednego elementu listy (indeksowanie zaczyna się od 0):
>>> L1[1]
(5, 6)
>>> type(L1[1])
<type 'tuple'>
Aha! Każdy element L1 jest w rzeczywistości krotką. Właśnie to musimy przekazać, aby usunąć (). Krotki w pythonie są bardzo proste, są po prostu tworzone przez umieszczanie wartości w nawiasach. „a, b” nie jest krotką, ale „(a, b)” jest krotką. Zmodyfikujemy więc Twój kod i uruchomimy go ponownie:
# The remove line now includes an extra "()" to make a tuple out of "a,b"
L1.remove((a,b))
Ten kod działa bezbłędnie, ale spójrzmy na listę, którą wypisuje:
L1 is now: [(1, 2), (5, 6), (1, -2)]
Dlaczego (1, -2) jest nadal na twojej liście? Okazuje się, że modyfikowanie listy podczas iteracji w pętli jest bardzo złym pomysłem bez specjalnej uwagi. Powodem, dla którego (1, -2) pozostaje na liście, jest to, że lokalizacje każdego elementu na liście zmieniały się między iteracjami pętli for. Zobaczmy, co się stanie, jeśli podamy powyższy kod dłuższą listę:
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)]
Jak można wywnioskować z tego wyniku, za każdym razem, gdy instrukcja warunkowa ma wartość true, a element listy jest usuwany, następna iteracja pętli pomija ocenę następnego elementu na liście, ponieważ jego wartości są teraz zlokalizowane w różnych indeksach.
Najbardziej intuicyjnym rozwiązaniem jest skopiowanie listy, a następnie iterowanie oryginalnej listy i modyfikowanie tylko kopii. Możesz spróbować zrobić to w ten sposób:
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)
Jednak dane wyjściowe będą identyczne jak wcześniej:
'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]
Wynika to z faktu, że kiedy stworzyliśmy L2, Python tak naprawdę nie utworzył nowego obiektu. Zamiast tego odwoływał się jedynie do L2 do tego samego obiektu co L1. Możemy to zweryfikować za pomocą „is”, który różni się od zwykłego „equals” (==).
>>> L2=L1
>>> L1 is L2
True
Możemy wykonać prawdziwą kopię za pomocą copy.copy (). Wtedy wszystko działa zgodnie z oczekiwaniami:
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)]
Wreszcie istnieje jedno czystsze rozwiązanie niż konieczność zrobienia całkowicie nowej kopii L1. Funkcja 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)]
Niestety nie potrafię odpowiednio opisać, jak działa reverse (). Zwraca obiekt „listreverseiterator”, gdy lista jest do niego przekazywana. Ze względów praktycznych można go traktować jako tworzenie odwróconej kopii jego argumentu. To rozwiązanie polecam.