Я пытаюсь написать визуализатор оценки экспрессии Python, который покажет, как выражения Python оцениваются шаг за шагом (для образовательных целей). Philip Guo Python Tutor отлично работает, но он оценивает программу Python по очереди, и я обнаружил, что студенты иногда не понимают, как оцениваются однострочные выражения, такие как sorted([4, 2, 3, 1] + [5, 6])[1] == 2
, и я хотел бы визуализировать этот процесс. (Похоже, что никто этого не делал - по крайней мере, я ничего не нашел.) Идеальное решение создаст последовательность таких строк:
sorted([4, 2, 3, 1] + [5, 6])[1] == 2
sorted( >> [4, 2, 3, 1] + [5, 6] << )[1] == 2
>> sorted([4, 2, 3, 1, 5, 6]) << [1] == 2
>> [1 2 3 4 5 6][1] << == 2
>> 2 == 2 <<
True
Здесь >>
и <<
используются для выделения части выражения, которое оценивается на текущем шаге, а затем заменяется на его значение. (Возможно, я попытаюсь преобразовать эту последовательность в некоторую анимацию позже.)
Моя текущая стратегия - использовать ast.parse()
для синтаксического анализа строки в AST, а затем найти node, который будет оцениваться первым, оценить его с помощью eval(compile(node, '', 'eval'))
(я определенно не хочу переопределять весь Python:)), преобразуйте результат оценки в AST node (с repr
, а затем ast.parse()
?) и замените текущий node на результат node, затем используйте codegen.to_source
для создания модифицированной строки кода из (изменено) AST и продолжить тот же процесс, пока в дереве не будет только одного литерала.
Мой вопрос: как я могу найти node, который будет оцениваться первым? Кажется, что я могу пересекать глубину дерева - сначала с помощью подкласса ast.NodeVisitor
, но я не уверен, как я могу обнаружить, что достиг желаемого node, и как я могу остановить перемещение после него?
ИЗМЕНИТЬ.
Возможно, мой первоначальный подход с преобразованием дерева невозможен. Фактически, элементарный шаг оценки выражения Python не обязательно должен быть заменой некоторого подвыражения более простому (как в арифметике). Например, понимание списков обеспечивает гораздо более сложное поведение, которое не может быть выражено в терминах, заменяющих эту вещь этой штукой, а затем повторяется рекурсивно. Поэтому я немного переформулирую вопрос. Мне нужно каким-то образом программно показать, как выражения Python оцениваются шаг за шагом. Например, функция MacroPy tracing, упомянутая @jasonharper, является приемлемым решением на данном этапе. К сожалению, MacroPy, кажется, оставлен и не работает с Python 3. Есть ли какие-либо идеи, как напоминать это поведение трассировки в Python 3 без портирования полного MacroPy?
EDIT2.
Сразу после того, как я наградил эту награду, я нашел аналогичный вопрос и отладчик с очень близкими функциями. Однако, поскольку нет окончательного ответа на этот вопрос, и мне не нужен полный отладчик, я все еще ищу ответ, который можно использовать, например, в среде Jupyter.