Ответ 1
Как уже говорилось, это выглядит как ошибка документации. Документация для объектов кода явно противоречит документации для inspect
:
co_varnames
кортеж, содержащий имена локальных переменных (начиная с имен аргументов); [...]co_names
представляет собой кортеж , содержащий имена, используемые байт-кодом;
Кроме того, доступ к атрибутам co_names
и co_varnames
объектов кода противоречит тому, что было указано в inspect
:
>>> def f():
... a = 1
... b = 2
...
>>> f.__code__.co_names
()
>>> f.__code__.co_varnames
('a', 'b')
Кроме того, комментарии в исходном коде компилятор CPython явно указывают, что co_varnames
для локальных переменных:
PyObject *u_names; /* all names */
PyObject *u_varnames; /* local variables */
Причина, по которой вы не видите co_varnames
, состоит в том, что вышеупомянутый код инициализирует атрибуты для объекта компилятора, который использует Python для компиляции кода. u_names
и u_varnames
обе позже передаются в PyCode_New
- конструктор для объектов кода CPython:
names = dict_keys_inorder(c->u->u_names, 0);
varnames = dict_keys_inorder(c->u->u_varnames, 0);
...
co = PyCode_New(..., names, varnames, ... );
И PyCode_New
присваивает names
и varnames
атрибутам co_names
и co_varnames
соответственно:
Py_INCREF(names);
co->co_names = names;
Py_INCREF(varnames);
co->co_varnames = varnames;
Если вы уже этого не сделали, я предлагаю заполнить отчет об ошибке в bugs.python.org, чтобы команда разработчиков Python знала об этой несогласованности в документация.