2013-05-16 2 views
2

У меня есть проблемы с заполнением следующей функции:получить полное имя методы из инспектировать стек

def fullyQualifiedMethodNameInStack(depth=1): 
    """ 
    The function should return <file>_<class>_<method> for the method in the 
    stack at specified depth. 
    """ 
    fileName=inspect.stack()[depth][1] 
    methodName=inspect.stack()[depth][3] 
    class= """ please help!!! """ 
    baseName=os.path.splitext(os.path.basename(fileName))[0] 
    return '{0}_{1}_{2}'.format(baseName, className, methodName) 

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

+0

1) Вы можете видеть только функции, а не методы, 2) вы можете только дать обоснованное предположение относительно типа экземпляра. Это не то же самое, что класс, изначально определяемый методом. Этого достаточно? –

+0

Ну, я надеялся, что будет возможность узнать, в каком классе определена функция, без угадывания. Какая самая образованная догадка я могу взять? –

+0

@MartijnPieters Я заинтригован по поводу пункта 2. 'inspect.stack()' только кажется, последовательно возвращает имена функций, а не объекты функции. – millimoose

ответ

1

Вы всегда смотрите на функцию context; контекст метода уже ушел к моменту выполнения функции. С технической точки зрения, functions act as descriptors при доступе в качестве атрибутов экземпляра (instance.method_name), которые возвращают объект метода. Объект метода затем, когда он вызывается, в свою очередь вызывает исходную функцию с экземпляром в качестве первого аргумента. Поскольку это все происходит в коде C, в стеке Python не остается следов исходного объекта метода.

Стек должен только отслеживать пространства имен и код, который должен быть выполнен для локального пространства имен. Исходный функциональный объект больше не нужен для этих функций, только прикрепленный объект кода по-прежнему сохраняет имя исходного определения функции для целей трассировки.

Если вы знаете, то функция, которая будет методом, вы можете найти локальное имя self. Если присутствует, type(self) - это класс экземпляра , который не обязательно является классом, на котором был определен метод.

Вам необходимо будет выполнить поиск по классу и его базам (зацикливание по атрибуту .__mro__), чтобы попытаться определить, какой класс определил этот метод.

Есть еще несколько коряг, которые необходимо принять во внимание:

  • Именование первого аргумента метода self лишь условность. Если кто-то выбрал другое имя, вы не сможете это понять, не разобрав исходный код Python, или, перейдя еще на один шаг в стек, и попытайтесь вывести из , что строка, как вызвана функция, затем извлекает метод и атрибут .im_self.

  • Вам предоставляется только исходное имя функции, под которой оно было определено. Это не обязательно имя, под которым оно было вызвано. Функции являются первоклассными объектами и могут быть добавлены в классы под разными именами.

  • Хотя функция была передана в self и была определена как часть определения класса, она могла бы быть вызван вручную проходя значение для self вместо обычного маршрута метода (являющийся результат функция, действующая как дескриптор), проходящая по ссылке self для вызывающего абонента.

В Python 3.3 и выше ситуация немного лучше; объекты функции имеют новый __qualname__ attribute, который будет включать имя класса. Проблема заключается в том, что вам все равно нужно найти объект функции из фрейма родительского стека.

Смежные вопросы