Самоанализ Python: как определить, к каким полям обращаются из метода - PullRequest
4 голосов
/ 02 декабря 2011

Мне нужно выполнить какое-то черное и грязное волшебство с Python.

Следуя моему предыдущему вопросу Свойства Lazy data-flow (наподобие электронной таблицы) с зависимостями в Python Теперь я хотел быЗаполните список полей, от которых зависит производное свойство, автоматически проверяя функцию вычисления.

Я думаю, что мог бы использовать атрибут func_code.co_names, но я не совсем уверен, есть ли какие-то предостережения и документация не сильно помогает.

Есть идеи?

1 Ответ

2 голосов
/ 05 января 2012

К сожалению, func_code.co_names вряд ли сильно поможет.Он содержит все имена, к которым осуществляется доступ в сегменте кода, включая глобальные переменные, в порядке их появления.

class Test(object):
    def calc_a(self):
        return self.b + self.c

    def calc_x(self):
        return self.y.a + self.y.b

>>> Test.calc_a.func_code.co_names
('b', 'c')
>>> Test.calc_x.func_code.co_names
('y', 'a', 'b')

Невозможно определить из этого массива, загружены ли 'a' и 'b' из '«Я» или «Я. я».Как правило, единственный способ узнать схему доступа к коду без его выполнения - это разобрать его.

>>> import dis
>>> dis.dis(Test.calc_x)
 23           0 LOAD_FAST                0 (self)
              3 LOAD_ATTR                0 (y)
              6 LOAD_ATTR                1 (a)
              9 LOAD_FAST                0 (self)
             12 LOAD_ATTR                0 (y)
             15 LOAD_ATTR                2 (b)
             18 BINARY_ADD          
             19 RETURN_VALUE        

Мы видим, что функция загружает переменную self (которая всегда co_varnames[0]).для связанной функции), затем из этого объекта загружается атрибут 'y' (co_names[0]), а затем из этого объекта загружается атрибут 'a' (co_names[1]).Второй объект стека выталкивается из self.yb, затем добавляются два.

Посмотрите на источник dis.py в стандартной библиотеке lib, чтобы увидеть, как разбирается двоичный код на языке Python C.Загрузка 0-й переменной будет важна для связанных функций.Еще один полезный момент: аргументы функции: co_varnames[:co_argcount] (остальные или переменные - локальные), а co_freevars - переменные из включенной неглобальной области.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...