Найти - Пользователи
Полная версия: поведение вложенных циклов
Начало » Python для новичков » поведение вложенных циклов
1
APytB
Пытаюсь разобраться со вложенными списками и вложенными списками. Вот такой пример кода. Не понимаю следующее. Я задаю элемент, в который добравляю числа от 0 до j, а сам j oт 0 до i. Если я задаю элемент (внутренний список) внутри цикла i (el2 в примере), то все понятно и хорошо, он при переходе к новому i обнуляется, логично. Но, если элемент задан ДО цикла i (el1), то вот тут все странно. Почему он цепляет все значения j i раз? Т.е. 2 вещи смущают. 1) как он обнуляется при переходе к новому i? 2) как так внутри меньшего i у этого цикла оказываются в доступе j большего значения? т.е. на прогоне i равного 1, почему-то есть и j = 1 и j = 2. Как так?


 ml1, ml2, el1 = [], [], []
for i in range(4):
    el2 = []
    for j in range(i):
        print(i, j)
        el1.append(j)
        el2.append(j)
    ml1.append(el1)
    ml2.append(el2)
print(ml1, ml2, sep='\n')
OUTPUT
1 0
2 0
2 1
3 0
3 1
3 2
[[0, 0, 1, 0, 1, 2], [0, 0, 1, 0, 1, 2], [0, 0, 1, 0, 1, 2], [0, 0, 1, 0, 1, 2]]
[[], [0], [0, 1], [0, 1, 2]]
py.user.next
APytB
Если я задаю элемент (внутренний список) внутри цикла i (el2 в примере), то все понятно и хорошо, он при переходе к новому i обнуляется, логично.
Он не обнуляется, а выбрасывается. А вместо него создаётся новый пустой список. Соответственно, у разных списков разные адресы в памяти и разное содержимое. На следующем круге происходит то же самое и остаётся уже три списка с разными адресами в памяти и разным содержимым. И так далее. И вот эти разные списки добавляются в список ml2. У них разные адресы в памяти и разное содержимое у всех.

APytB
Но, если элемент задан ДО цикла i (el1), то вот тут все странно. Почему он цепляет все значения j i раз? Т.е. 2 вещи смущают. 1) как он обнуляется при переходе к новому i?
Он не обнуляется, а остаётся и продолжает заполняться дальше. У него один адрес в памяти и поэтому при его добавлении в список ml1 добавляется просто копия его адреса в памяти. Поэтому на каждом шаге ты добавляешь его же самого. А так как он растёт всё время, то к концу основного цикла этот список вырастает полностью.

  
>>> a = []
>>> lst = [a, a, a]
>>> lst
[[], [], []]
>>> a.append(1)
>>> lst
[[1], [1], [1]]
>>> a.append(2)
>>> lst
[[1, 2], [1, 2], [1, 2]]
>>> a.append(3)
>>> lst
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
>>>
>>> c = []
>>> d = []
>>> e = []
>>> 
>>> lst = [a, c, a, d, a, e]
>>> lst
[[1, 2, 3], [], [1, 2, 3], [], [1, 2, 3], []]
>>> c.append(10)
>>> lst
[[1, 2, 3], [10], [1, 2, 3], [], [1, 2, 3], []]
>>> d.append(20)
>>> lst
[[1, 2, 3], [10], [1, 2, 3], [20], [1, 2, 3], []]
>>> e.append(30)
>>> lst
[[1, 2, 3], [10], [1, 2, 3], [20], [1, 2, 3], [30]]
>>> a.append(4)
>>> lst
[[1, 2, 3, 4], [10], [1, 2, 3, 4], [20], [1, 2, 3, 4], [30]]
>>>
APytB
py.user.next
Спасибо! Да, тогда понятно
Olezhka
Немного дополню py.user.next. Вот посмотри приложенное объяснение “12345.jpg”
А еще посмотри, как одна и та же переменная может иметь разный адрес в памяти (id):
 a = []
print('Адрес в памяти переменной "а" = ', id(a))
for i in range(4):
    b = []
    print('Адрес в памяти переменной "b" = ', id(b))
Вывод:
Адрес в памяти переменной “а” = 2899457290752
Адрес в памяти переменной “b” = 2899457288256
Адрес в памяти переменной “b” = 2899457346624
Адрес в памяти переменной “b” = 2899457355008
Адрес в памяти переменной “b” = 2899457288000

P.S. И не забывай, пожалуйста, ставить плюсики тем, кто тебе помог
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