Как работает цикл Python for? - PullRequest
0 голосов
/ 27 января 2019

Мне любопытно понять, как петли Python for работают под капотом. Я попытался реализовать это в некотором роде, как в следующем фрагменте кода. Так был реализован цикл for?

my_list = [1, 2, 3, 4, 5]

# list itself is iterable but not iterator. Make it an iterator
iter_list = iter(my_list)

while True:
    try:
       print(next(iter_list))
    except StopIteration:
       break

1 Ответ

0 голосов
/ 27 января 2019

Да, это хорошее приближение к тому, как реализована конструкция цикла for.Это, безусловно, соответствует документации оператора цикла for :

Список выражений вычисляется один раз;это должно привести к повторяемому объекту.Итератор создан для результата expression_list.Затем набор выполняется один раз для каждого элемента, предоставленного итератором, в порядке, возвращаемом итератором.Каждый элемент, в свою очередь, назначается целевому списку с использованием стандартных правил для назначений (см. Операторы назначения), а затем выполняется набор.Когда элементы исчерпаны (что происходит сразу же, когда последовательность пуста или итератор вызывает исключение StopIteration), выполняется набор в предложении else, если он присутствует, и цикл завершается.

Вы пропустили только , назначенный целевому списку, используя стандартные правила для присвоений part;вам придется использовать i = next(iter_list) и print(i), а не печатать результат вызова next() напрямую.

Исходный код Python компилируется в байт-код , который выполняет цикл интерпретатора.затем выполняет.Вы можете посмотреть байт-код для цикла for, используя модуль dis :

>>> import dis
>>> dis.dis('for i in mylist: pass')
  1           0 SETUP_LOOP              12 (to 14)
              2 LOAD_NAME                0 (mylist)
              4 GET_ITER
        >>    6 FOR_ITER                 4 (to 12)
              8 STORE_NAME               1 (i)
             10 JUMP_ABSOLUTE            6
        >>   12 POP_BLOCK
        >>   14 LOAD_CONST               0 (None)
             16 RETURN_VALUE

Различные названные коды операций задокументированы в одном и том же модуле dis, иих реализация может быть найдена в цикле оценки CPython (ищите цели переключения TARGET(<opcode>));приведенные выше коды операций разбиты на:

  • SETUP_LOOP 12 отмечает начало suite , блока операторов, поэтому интерпретатор знает, куда нужно перейтив случае break, и какую очистку необходимо выполнить в случае исключения или оператора return;код операции очистки располагается через 12 байт байт-кода после этого кода операции (поэтому POP_BLOCK здесь).
  • LOAD_NAME 0 (mylist) загружает значение переменной mylist, помещая его сверхустека ( TOS в описании кода операции).
  • GET_ITER вызывает iter() для объекта в TOS, затем заменяет TOS на результат.
  • FOR_ITER 4 вызывает next() на итераторе TOS.Если это дает результат, то это подталкивается к TOS.Если есть исключение StopIteration, итератор удаляется из TOS, и 4 байта байт-кода пропускаются в код операции POP_BLOCK.
  • STORE_NAME 1 принимает TOS ипомещает его в именованную переменную, здесь это i.
  • JUMP_ABSOLUTE 6 отмечает конец тела цикла;он говорит интерпретатору вернуться к смещению байт-кода 6 до приведенной выше инструкции FOR_ITER.Если мы сделали что-то интересное в цикле, то это произойдет после STORE_NAME, до того, как JUMP_ABSOLUTE.
  • POP_BLOCK удалит учетную запись блока, установленную на SETUP_LOOP, иудаляет итератор из стека.

Маркеры >> являются целями перехода, в качестве визуальных подсказок, чтобы упростить их обнаружение при чтении строки кода операции, которая к ним переходит.

...