Найти - Пользователи
Полная версия: Помогите разобраться в ошибке
Начало » Python для новичков » Помогите разобраться в ошибке
1
Bilbo
Есть такая программа:
 win_row = [(0,1,2),
           (3,4,5),
           (6,7,8),
           (0,3,6),
           (1,4,7),
           (2,5,8),
           (0,4,8),
           (2,4,6)]
MOVES = [4,0,2,7]
for i in win_row:
    for j in MOVES:
        if j in i:
            print ("\n", j, "-", i, "id of i -", id(i), "id of element -", id(win_row[win_row.index(i)]), win_row)
            win_row.remove(i)
Не понимаю, почему появляется ошибка. Удаляю элемент, но переменная, которая на него ссылалась не обнуляется. В чем подвох?
py.user.next
Нельзя менять список, который перебираешь (в общем случае). Чтобы это исправить, перебирай копию.

Bilbo
 for i in win_row:
 for i in win_row[:]:

И у копии будут другие id(), но это и не важно, потому что само использование id() вызывает вопросы.
PEHDOM
Bilbo
Удаляю элемент, но переменная, которая на него ссылалась не обнуляется.
А с чего она должна обнуляться?
вот у вас написано
 if j in i:
            win_row.remove(i)
допустим перрвое же сравнение выдаст True, вы радостно удаляете i, что оно будет дальше удалять? нужно превать цикл, после удаления…
Дальше удалили вы первый элемент списка,на его место станет следующий, индексы всех элемнтов сдвинулись, первый стал нулевым, второй первым и т.д. как вы думаете какой элемент for возьмет следующим? нулевой он взял, следовательно возьмет первый, но первый уже имеет индекс 0, тоесть по факту он возьмет второй элемент из “изначального” списка, а первый у вас вообще проигнориться…
Вобщемто py.user.next говорит правильно, нельзя менять список который перебираешь, но если очнь хочеться или нужно, лабораторная там или задание где нжно решить задачу именно таким путем, то for тут использовать нельзя, нужно использвать while
 win_row = [(0,1,2),
           (3,4,5),
           (6,7,8),
           (0,3,6),
           (1,4,7),
           (2,5,8),
           (0,4,8),
           (2,4,6),
           ]
MOVES = [4,0,2,7]
i=0                                                 #начальный индекс
while i < len(win_row):                    # пока i менше длинны списка
    for j in MOVES:               
        if j in win_row[i]:                       #если в элемнте списка есть число из MOVES
            win_row.remove(win_row[i])  # удалить элемент
            break                                   # прервать цикл
    else:                                       # если цикл завершился без  break 
        i+= 1                                  # увеличиваем индекс на 1
print(win_row)
Bilbo
PEHDOM
допустим перрвое же сравнение выдаст True, вы радостно удаляете i, с чем будет оно дальше сравнивать? нужно превать цикл, после удаления…
Проблема в том, что внутри списка удаляется кортеж, на этот кортеж ссылается переменная i. По моему разумению после удаление кортежа, i должна выдавать None. Но вместо этого i не обнуляется, элементы списка j продолжают искаться в i, хотя самого i уже существовать не должно.

 for j in MOVES:
        if j in i:
            win_row.remove(i)

Представляю это так:
Ищем 4 в (0,1,2)
Ищем 0 в (0,1,2)
0 найдена в (0,1,2)
удаляем (0,1,2)
*Ищем 2 в (0,1,2)
2 найдена в (0,1,2)
пытаемся удалить (0,1,2)
ОШИБКА: (0,1,2) на найдена в списке

Мне кажется, что после (*) должно выглядеть так:
*Ищем 7 в None

далее интерпретатор переходит на следующий кортеж - (3,4,5).

Т. е. почему после удаления (0,1,2) переменная i не принимает значение None? Хочу понять, что принимает i. Получается, что i ссылается на другой участок памяти в отличие от win_row (где k - это порядковый номер элемента равный i). Получается, что i = win_row, либо i = (0,1,2). И здесь мы имеем второй вариант?
PEHDOM
Bilbo
Проблема в том, что внутри списка удаляется кортеж, на этот кортеж ссылается переменная i. По моему разумению после удаление кортежа, i должна выдавать None.
Скуяли? i ссылаеться на кортеж, и win_row 0,например, ссылаеться на тот же кортеж.Данные остаються в памяти пока на них ссылается хотябы одна переменная. В данном случае на него ссылеться i и он будет в памяти до конца итерации for. После того как i примет следующее значение, сборщик мусора “увидит” что на кортеж больше нет ни одной ссылки и освободит память занимаемую кортежем.

То что вы удалили кортеж из списка, означает что вы удалили ссылку на кортеж из списка, а не кортеж из памяти. Это никак не обнуляет i на None.
Bilbo
Хочу понять, что принимает i. Получается, что i ссылается на другой участок памяти в отличие от win_row (где k - это порядковый номер элемента равный i). Получается, что i = win_row, либо i = (0,1,2). И здесь мы имеем второй вариант?
i = (0,1,2) даже если вы удалите этот кортеж из списка кортеж остеться в памяти пока на него указывает хотябы одна переменная. i будет указывать на этот кортеж пока ее не переназначат или не удалят.
Bilbo
Спасибо, PEHDOM. Я запутался. Мне почему-то казалось, что удалив кортеж, он именно удалится. Читал Доусона, там есть раздел “распределенные ссылки”. Пример такой:
i = [1,2,3]
j = i
k = i
del j[0]
print (k)
>>> [2,3]
По аналогии мне показалось, что должно работать также в вышеобозначенном случае. Но теперь запутался как это работает.
PEHDOM
Bilbo
Мне почему-то казалось, что удалив кортеж, он именно удалится.
Нет, он удалиться только из списка, если на него указвает еще какаянибудь переменная он останеться в памяти.
Python имеет автоматическое управление памятью: подсчёт ссылок для большинства объектов и сборка мусора для удаления циклов. Память освобождается сразу после того, как была удалена последняя ссылка на объект.
https://ru.wikibooks.org/wiki/Python/%D0%A3%D1%87%D0%B5%D0%B1%D0%BD%D0%B8%D0%BA_Python_3.1
в догонку для болшего понимания
Все объекты делятся на ссылочные и атомарные. К атомарным относятся int, long (в версии 3 любое число int, так как в версии 3 нет ограничения на размер), complex и некоторые другие. При присваивании атомарных объектов копируется их значение, в то время как для ссылочных копируется только указатель на объект, таким образом, обе переменные после присваивания используют одно и то же значение. Ссылочные объекты бывают изменяемые и неизменяемые….
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB