Модуль dis Python: аудит повторяющихся инструкций LOADGLOBAL
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Профилирование Python: задачи на cProfile, pstats и байт-код dis.
Аудит повторяющихся глобальных обращений
При оптимизации расчётного модуля физического симулятора инженеры проверяют байт-код функций, чтобы исключить медленные обращения к глобальной области видимости LOAD_GLOBAL внутри циклов. Анализатор принимает функцию и инспектирует поток её инструкций, отслеживая все имена переменных и функций, загружаемые из глобального пространства.
Если одно и то же имя запрашивается через глобальный доступ строго больше одного раза на протяжении тела функции, оно признаётся неоптимизированным кандидатом для локализации — кэширования в локальную переменную. Обращения, встречающиеся ровно один раз, считаются допустимыми и в отчёт не попадают.
Реализуйте функцию аудита байт-кода, которая находит такие повторяющиеся обращения и возвращает упорядоченный по алфавиту список всех глобальных имён, загружаемых более одного раза.
Что уже дано
В редакторе импортирован модуль dis и подготовлена заготовка функции repeated_globals. В тестовом окружении также доступны вспомогательные функции make_global_audit_target(source) и observe_global_audit_target(target), но реализовывать их заново не требуется.
Что нужно сделать
Реализуйте функцию repeated_globals(func) -> list[str].
Функция принимает обычную функцию CPython func (включая функции с замыканиями, ветвлениями, циклами или вложенными определениями) и возвращает отсортированный по алфавиту (в лексикографическом порядке возрастания) список уникальных строк — имён, для которых в собственном потоке инструкций func встречается строго больше одной статической инструкции LOAD_GLOBAL.
Правила проверки:
- Анализ выполняется статически по реальному байт-коду: вызывать саму функцию
funcзапрещено. - Учитываются только статические места инструкций в кодовом объекте самой функции, а не число итераций во время выполнения (одна инструкция
LOAD_GLOBALвнутри цикла считается ровно за одно вхождение). - Встроенные функции и константы (
builtins), загружаемые черезLOAD_GLOBAL, учитываются по тем же правилам, что и пользовательские глобальные переменные. - Используйте разрешённое строковое имя переменной (
argval), а не форматированное строковое представление (argrepr), которое в Python 3.12 может содержать префиксы вродеNULL +. - Все остальные опкоды (например,
LOAD_FAST,LOAD_ATTR,LOAD_DEREF) полностью игнорируются. - Не углубляйтесь рекурсивно во вложенные функции или генераторные выражения: проверяется только собственный поток инструкций переданной функции.
- Если подходящих повторяющихся имён нет, функция должна вернуть пустой список
[].
Ограничения:
- количество инструкций в исследуемой функции не превышает 10 000;
- длина имени глобальной переменной не превышает 100 символов.
Обратите внимание: это эвристический статический аудит байт-кода, а не измерение времени исполнения или гарантия ускорения.
Ввод и вывод
Стандартные потоки stdin и stdout не используются: считывать ввод и вызывать print() не нужно. Проверяющая система выполняет код решения и получает функцию верхнего уровня repeated_globals напрямую из состояния скрипта.
Пример использования
def kernel(x):
return scale(x) + scale(x) + offset
print(repeated_globals(kernel))
Вывод:
['scale']
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- CProfile Python: разница между tottime и cumtime в отчёте
- CProfile и pstats: найдите доминирующую операцию в профиле Python
- Модуль dis Python: найдите инструкции возврата в байт-коде
- Удаление ключа из ChainMap в Python: проверка поведения del
- Обратный индекс на Python: группировка уникальных значений через defaultdict
- Подсчёт дефицита ресурсов в Python: квоты и суммы заявок
