Алгоритм Python euclid, пытающийся понять [дубликат]

Если вы хотите, если из командной строки. Просто запустите команду ниже с пути к проекту

mvn assembly: assembly

22
задан Martijn Pieters 16 April 2016 в 13:00
поделиться

1 ответ

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

Для назначений кортежей с 2 ​​или 3 элементами Python просто использует стек напрямую:

>>> import dis
>>> def foo(a, b):
...     a, b = b, a
... 
>>> dis.dis(foo)
  2           0 LOAD_FAST                1 (b)
              3 LOAD_FAST                0 (a)
              6 ROT_TWO             
              7 STORE_FAST               0 (a)
             10 STORE_FAST               1 (b)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE        

После двух LOAD_FAST опкодов (которые выталкивают значение из переменной на стек), верхняя часть стека содержит [a, b]. Код операции ROT_TWO заменяет верхние две позиции в стеке, поэтому стек теперь имеет [b, a] вверху. Два STORE_FAST opcodes затем берут эти два значения и сохраняют их в именах в левой части присваивания. Первый STORE_FAST выводит значение вершины стека и помещает его в a, затем снова появляется вспять, сохраняя значение в b. Вращение необходимо, потому что Python гарантирует, что назначения в целевом списке с левой стороны выполняются слева направо.

Для назначения 3-имени, ROT_THREE а затем ROT_TWO выполняется, чтобы отменить три верхних элемента в стеке.

Для более длинных назначений слева строит явный кортеж:

>>> def bar(a, b, c, d):
...     d, c, b, a = a, b, c, d
... 
>>> dis.dis(bar)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_FAST                1 (b)
              6 LOAD_FAST                2 (c)
              9 LOAD_FAST                3 (d)
             12 BUILD_TUPLE              4
             15 UNPACK_SEQUENCE          4
             18 STORE_FAST               3 (d)
             21 STORE_FAST               2 (c)
             24 STORE_FAST               1 (b)
             27 STORE_FAST               0 (a)
             30 LOAD_CONST               0 (None)
             33 RETURN_VALUE        

Здесь стек с [d, c, b, a] используется для сборки кортежа (в обратном порядке снова появляется BUILD_TUPLE из стека, нажимая полученный кортеж в стек), а затем UNPACK_SEQUENCE снова выталкивает кортеж из стека, снова выталкивает все элементы из кортежа обратно в стек для операций STORE_FAST.

Последний может показаться расточительной операцией, но правильный - сторона стороны присваивания может быть чем-то совершенно другим, вызов функции, который создает кортеж, возможно, поэтому интерпретатор Python не делает предположений и всегда использует код операции UNPACK_SEQUENCE. Он делает это даже для операций назначения двух и трех имен, , но более поздняя (оптимизация) шаг оптимизации заменяет комбинацию BUILD_TUPLE / UNPACK_SEQUENCE с 2 или 3 аргументами с указанным выше ROT_TWO и ROT_THREE для эффективности.

57
ответ дан Martijn Pieters 26 August 2018 в 11:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: