#python #python-3.x #python-2.7
#python #python-3.x #python-2.7
Вопрос:
У меня есть небольшой вопрос, позвольте мне поделиться небольшим фрагментом кода
num = [1, 2, 3, 4]
for i in num:
print(i)
num[2] = 5
здесь вывод
1
2
5
4
значение итератора было обновлено до 5 вместо 3 на 3-й итерации, теперь, если я сделаю это
num = [1, 2, 3, 4]
for i in num:
print(i)
num = [5 if j == 3 else j for j in num]
вывод
1
2
3
4
итератор остался прежним на 3-й итерации
Кто-нибудь знает причину такого поведения?
(Я наблюдал это в Python 3.8 или 2.7)
Комментарии:
1. Общая идея состоит в том, чтобы не обновлять коллекцию, которую вы перебираете в цикле. кстати, в ваших примерах кода нет итераторов.
2.
for
Цикл получает итератор один разnum
в начале цикла, который затем просматривает каждое значение в списке одно за другим.num = ...
заменяет переменнуюnum
другим списком, но это не представляет интереса дляfor
цикла, потому что он не просматриваетсяnum
снова после того, как он уже получил свой итератор.3. Ваш первый пример изменяет список; ваш второй пример создает новый список и присваивает его
num
, пока вы продолжаете перебирать исходный список.
Ответ №1:
Когда вы запускаете цикл for, он принимает идентификатор предоставленного объекта и выполняет итерацию по нему.
В первом фрагменте кода вы изменяете элемент исходного объекта, поэтому, когда итератор достигает второго элемента, он принимает обновленное значение.
Однако во втором случае вы создаете новый объект с другими значениями, но объект, который вы предоставили циклу, остается неизменным.
Способ проверить это поведение — получить идентификатор переменной до и после изменений и посмотреть, как он не меняется в первом случае, но меняется во втором случае:
my_list = [1, 2, 3]
original_id = id(my_list)
# Check if the object identification changes after modifying one element
my_list[2] = 4
new_id = id(my_list)
if original_id == new_id:
print("1st case: The ID stays the same")
else:
print("1st case: The ID has changed")
# Check now what happens if you create a new list
my_list = [3, 2, 1]
new_id = id(my_list)
if original_id == new_id:
print("2nd case: The ID stays the same")
else:
print("2nd case: The ID has changed")
Полученный результат следующий:
1st case: The ID stays the same
2nd case: The ID has changed
Комментарии:
1. Рад, что это помогло. Если вам интересно узнать больше об этой теме, выполните поиск по изменяемым и неизменяемым объектам в Python 😉
Ответ №2:
В вашем первом коде вы num[2]=5
заменяете значения в самом экземпляре первого цикла, поэтому 5 печатается в обычном цикле.
Ваш второй код:
На самом деле он заменяет и i
печатается только во втором коде.
Вам нужно распечатать num
, чтобы проверить замененное значение.
Код:
num = [1, 2, 3, 4]
for i in num:
print(i)
num = [5 if j==3 else j for j in num ]
print (num)# This line
Вывод:
1
2
3
4
[1, 2, 5, 4]
Комментарии:
1. Да, но я хотел знать, почему «i» не обновлялся как предыдущий.
2. Также объясняется в ответе. На самом деле он мутировал в первом экземпляре самого lopp. Итак, 5 печатается в экземпляре 3-го цикла.
Ответ №3:
for
Цикл уже получает итератор num
, и в то время как внутри цикла вы изменяете num
, for
цикл больше не просматривается num
и повторяется с использованием старого списка.