Да, это хорошее приближение к тому, как реализована конструкция цикла 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
, иудаляет итератор из стека.
Маркеры >>
являются целями перехода, в качестве визуальных подсказок, чтобы упростить их обнаружение при чтении строки кода операции, которая к ним переходит.