Этот ответ был первоначально написан в ответ на вопрос, который с тех пор был отмечен как дубликат: Удаление координат из списка на python
В вашем коде есть две проблемы:
1) При использовании remove () вы пытаетесь удалить целые числа, тогда как вам нужно удалить кортеж.
2) Цикл for пропустит элементы в вашем списке.
Давайте рассмотрим, что произойдет, когда мы выполним ваш код:
>>> 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 "", line 3, in
TypeError: remove() takes exactly one argument (2 given)
. Первая проблема заключается в том, что вы передаете «a» и «b» для удаления (), но remove () only принимает единственный аргумент. Итак, как мы можем заставить remove () работать с вашим списком? Нам нужно выяснить, что представляет собой каждый элемент вашего списка. В этом случае каждый из них является кортежем. Чтобы увидеть это, давайте обратимся к одному элементу списка (индексирование начинается с 0):
>>> L1[1]
(5, 6)
>>> type(L1[1])
Aha! Каждый элемент L1 на самом деле является кортежем. Так вот что нам нужно передать remove (). Кортежи в python очень просты, они просто создаются путем включения значений в круглые скобки. «a, b» не является кортежем, но «(a, b)» является кортежем. Итак, мы модифицируем ваш код и запускаем его снова:
# The remove line now includes an extra "()" to make a tuple out of "a,b"
L1.remove((a,b))
Этот код работает без какой-либо ошибки, но давайте посмотрим на его список:
L1 is now: [(1, 2), (5, 6), (1, -2)]
Почему (1 , -2) все еще в вашем списке? Оказывается, изменение списка при использовании цикла для итерации по нему - очень плохая идея без особой осторожности. Причина, по которой (1, -2) остается в списке, состоит в том, что расположение каждого элемента в списке изменилось между итерациями цикла for. Давайте посмотрим, что произойдет, если мы будем кормить приведенный выше код более длинным списком:
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)]
Как вы можете сделать вывод из этого результата, каждый раз, когда оператор условного выражения имеет значение true и элемент списка удаляется, следующая итерация цикла пропустит оценку следующего элемента в списке, потому что его значения теперь расположены с разными индексами.
Наиболее интуитивно понятным решением является копирование списка, затем повторение по исходному списку и только изменить копию. Вы можете попробовать сделать это так:
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)
Однако выход будет идентичным предыдущему:
'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]
Это происходит потому, что, когда мы создали L2, python фактически не выполнял создать новый объект. Вместо этого он просто ссылался на L2 на тот же объект, что и на L1. Мы можем проверить это с помощью «is», который отличается от просто «равно» (==).
>>> L2=L1
>>> L1 is L2
True
Мы можем сделать истинную копию с помощью copy.copy (). Затем все работает так, как ожидалось:
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)]
Наконец, есть одно более чистое решение, чем необходимость создания совершенно новой копии L1. Функция 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)]
К сожалению, я не могу адекватно описать, как работает reverse (). Он возвращает объект «listreverseiterator», когда ему передается список. Для практических целей вы можете думать о нем как о создании обратной копии своих аргументов. Это рекомендуемое мной решение.
Если вы хотите получить доступ к переменным какой-то динамике, вы можете использовать отражение. Однако Reflection работает не для локальных переменных. Это применимо только для атрибутов класса.
Грубый быстрый и грязный пример:
public class T {
public Integer n1;
public Integer n2;
public Integer n3;
public void accessAttributes() throws IllegalArgumentException, SecurityException, IllegalAccessException,
NoSuchFieldException {
for (int i = 1; i < 4; i++) {
T.class.getField("n" + i).set(this, 5);
}
}
}
Вам нужно улучшить этот код различными способами, это только пример. Это также не считается хорошим кодом.