Посмотрите на вывод inspect.stack()
при переносе метода. Когда ваш декоратор выполняется, текущий кадр стека является вызовом функции вашего декоратора; следующий кадр стека вниз - это действие обтекания @
, которое применяется к новому методу; и третий кадр будет самим определением класса, который заслуживает отдельного стекового кадра, потому что определение класса является его собственным пространством имен (которое оборачивается, чтобы создать класс, когда оно выполнено).
Я предлагаю, поэтому:
defined_in_class = (len(frames) > 2 and
frames[2][4][0].strip().startswith('class '))
Если все эти сумасшедшие индексы выглядят неуправляемыми, то вы можете быть более явными, разбирая кадр по частям, например так:
import inspect
frames = inspect.stack()
defined_in_class = False
if len(frames) > 2:
maybe_class_frame = frames[2]
statement_list = maybe_class_frame[4]
first_statment = statement_list[0]
if first_statment.strip().startswith('class '):
defined_in_class = True
Обратите внимание, что я не вижу способ спросить Python об имени класса или иерархии наследования в момент запуска вашей оболочки; эта точка «слишком рано» на этапах обработки, поскольку создание класса еще не завершено. Либо проанализируйте строку, которая начинается с class
самостоятельно, а затем загляните в глобальные переменные этого фрейма, чтобы найти суперкласс, либо покопайтесь в объекте кода frames[1]
, чтобы увидеть, что вы можете выучить - кажется, что имя класса оказывается frames[1][0].f_code.co_name
в приведенном выше коде, но я не могу найти способ узнать, какие суперклассы будут присоединены, когда создание класса завершится.