Python — изменение переменной внутри for-цикла дает разные результаты

#python #c #r

#python #c #r

Вопрос:

Когда я пытаюсь:

 v = [1, 1]
for i in range(len(v)):
    v.append(1)
    print(v)
  

Вывод:

 [1, 1, 1]
[1, 1, 1, 1]
  

Но когда я делаю:

 v = [1, 1]
for i in v:
    v.append(1)
    print(v)
  

Это создает бесконечный цикл.

В обоих случаях значения range(len(v)) и v должны быть изменены внутри for-цикла. Может кто-нибудь объяснить, почему с этими двумя похожими кодами получаются разные результаты?

Когда я в дальнейшем попробую аналогичный код на R и C :

Для R:

 v <- c(1, 1)
for (i in v) v <- c(v, 1)
  
 v <- c(1,1)
for (i in seq_along(v)) v<-c(v, 1)
  

Для C :

 vector<int> v{1, 1};
for (auto i : v) v.push_back(1);
  

В результате v получается [1, 1, 1, 1] , что они имеют поведение, аналогичное поведению Python for i in range(len(v)): .

Но в C (и Java):

 vector<int> v{1, 1};
for (int i = 0; i < v.size(); i  ) v.push_back(1);
  

создает бесконечный цикл, указывающий на то, что он имеет поведение, аналогичное поведению Python for i in v: . Что происходит?

Комментарии:

1. В первом случае вы выполняете итерацию только дважды, изначально len(n) заданный размер. Во втором столько, сколько элементов находится в итерируемом. И поскольку вы добавляете значение на каждой итерации, это бесконечный итератор

2. range(len(n)) это объект диапазона, который был инициализирован значением len(n) . Почему объект range должен меняться во время итерации?

3. Как насчет языка R? for (i in v) дает результат, отличный от результата в Python.

4. Ваша первая попытка C имеет неопределенное поведение, поэтому может произойти что угодно.

5. Каждый язык имеет разные правила, разный синтаксис и т.д. Код C вызовет очевидный бесконечный цикл — вы изменяете размер вектора при каждом push_back() вызове, поэтому size() он будет продолжать увеличиваться., поэтому i никогда не догонит size() . Вам не нужны Java, python или R, чтобы увидеть это.

Ответ №1:

выполнение

 for i in var:
  

означает, что цикл будет выполняться для каждого элемента в var, затем в цикле вы добавляете элементы в var, создавая бесконечный цикл

 range(len(var))
  

однако повторяет цикл для количества элементов в var при запуске lopp, поэтому, когда цикл добавляется к циклу, запуск не продолжается

Ответ №2:

Здесь

 v = [1, 1]
for i in range(len(v)):
    v.append(1)
    print(v)
  

Вы повторяете список, который содержит [0 1] . Этот список составлен с использованием длины v , но в остальном не связан с v .

Здесь

 v = [1, 1]
for i in v:
    v.append(1)
    print(v)
  

Вы повторяете элементы v . Когда вы добавляете элементы v внутри цикла, вы никогда не доходите до конца.

Что касается C и R: это разные языки, поэтому не должно быть большим сюрпризом, что код, который выглядит похожим по синтаксису, делает что-то другое.

Ответ №3:

 v = [1, 1]
for i in v:
    v.append(1)
    print(v)
  

Когда вы выполняете приведенный выше код — это означает, что вы перебираете array/list - v — amp; внутри цикла, продолжая добавлять в него элементы — это никогда не закончится.

Когда вы выполняете код с len(v) помощью — len(v) будет оцениваться и назначаться как фиксированное количество раз для итерации.

Однако в идеале не следует путаться с переменной, используемой для определения количества итераций цикла внутри одного и того же цикла.

Ответ №4:

Это произошло потому, что на каждой итерации вашего цикла for вы обновляете свой вектор v. Затем, когда он будет запущен снова, он будет считывать вектор, больший, чем последняя итерация, что приведет, например, к бесконечному циклу:

  v = [1, 1]
 for i in v:
    v.append(1)
    print(v) ## By this point you have v = [1,1,1], then let`s start the loop again
 # v = [1, 1, 1]
 for i in v: # v now has the len(v) = 3, not 2. And it keeps getting bigger and bigger, resulting in an infinite loop.
    v.append(1)
    print(v) # now v = [1,1,1,1]

  

Лучший подход — установить ограничение на использование вашей итерации range .