0

Здравствуйте, есть следующий код:

x = 4
for i in range(x):
    for k in range(x):
        print(k)
        x = 2

Печатает:

0
1
2
3
0
1
0
1
0
1

Почему второй цикл for переоценивается на другое значение икса? Несмотря на то, что это значение находится в его теле. Однако, если написать такой же код, но с одним циклом, аналогичного переоценивания нет:

x = 4
for k in range(x):
        print(k)
        x = 2

Печатает:

0
1
2
3
jfs
  • 52,361
pinacol
  • 69
  • 1
    что значит "переоценивается" ? – Viktorov Mar 04 '18 at 10:21
  • То есть значение х изменяется с 4 на 2, потому что других причин, что код пишет 01 я не знаю – pinacol Mar 04 '18 at 10:24
  • Вы меняете значение "глобальной" переменной x с 4 на 2. Оно, что характерно, меняется: ваш код работает штатно. В чем проблема-то? – Dmitriy Simushev Mar 04 '18 at 10:26
  • Вы во вложенном цикле присвоили x = 2. После того как вложенный цикл завершился, выполняется вторая итерация внешнего цикла. Теперь строка for k in range(x): рассматривается заново и второй раз вложенный цикл выполняется с x равным 2. – Viktorov Mar 04 '18 at 10:26
  • А почему тогда в случае с одним циклом, изменение значения икса не влияет? – pinacol Mar 04 '18 at 10:27
  • 1
    количество итераций цикла рассчитывается при первом его выполнении. В первоначальном примере количество итераций вложенного цикла рассчитывается заново при каждой итерации внешнего цикла. По выводу вы можете увидеть, что внешний цикл по прежнему выполнил 4 итерации, в то время как внутренний первый раз сделал 4 итерации, а потом 3 раза по 2 итерации. – Viktorov Mar 04 '18 at 10:31

2 Answers2

4

range(x) выражение вычисляется ровно один раз для каждого цикла. В первом случае у вас четыре раза вычисляется range(x) при создании вложенного цикла. Во втором случае у вас ровно один цикл — изменения x после вычисления range(x) никакого влияния на уже созданный range объект не оказывают.

jfs
  • 52,361
4

Если добавить промежуточные переменные, то становится очевиден порядок создания объектов и использования значений

x = 4
range4 = range(x)   # x == 4
for i in range4:
    range2 = range(x)   # x == 4 на первой итерации, на остальных x == 2
    for k in range2:
        print(k)
        x = 2
Pavel
  • 396
  • То есть если циклы выполняются поочередно (сначала внешний, потом внутренний), то получается, что программа запоминает два разных значений икса? Для внешней ничего не меняется и икс равен 4, а во внутреннем икс после второй итерации равен 2 – pinacol Mar 05 '18 at 06:46
  • Цикл не запоминает значение икса. Цикл работает с объектом, созданным на базе значения икса, в данном случае - списками длины 4 или 2. Длина уже созданного списка не меняется при изменении значения х.

    То есть

    (1) сперва x = 4 (2) создали список А, в нём 4 объекта. И бежим по этому списку. (3) задали x = 2 (4) список А от этого никак не изменится, останется какой был (5) при создании нового списка используется новое значение х, и получается список содержащий 2 объекта.

    – Pavel Mar 05 '18 at 09:13
  • Спасибо за объяснение! – pinacol Mar 05 '18 at 10:09