Ваш декоратор не вызывается с помощью метода, он вызывается функцией.
Класс еще не существует, и этот метод не связывает эту функцию с классом, а тем более любой экземпляр класса и связанный метод связывает функцию с этим экземпляром. И даже если существуют методы do, они будут построены вокруг функции, которую возвращает ваш декоратор.
Таким образом, вы не можете понять функцию, которую вы получаете, чтобы попытаться получить ее класс, потому что у нее ее нет.
Есть различные Hacky трюков, которые вы можете использовать, чтобы определить, что вы находитесь в середине определения (хотя они могут быть специфическими для конкретной реализации Python и версию), но нет чистого способа сделать то, что вы хотеть. Например, вот один ужасный взлом:
self.classname = sys._getframe(1).f_code.co_name
Что это значит? Ну, ваш декоратор - это рамка 0; независимо от того, что называется рамкой 1.Если предмет, называемый им, является определением класса, его объект code
будет иметь имя класса в качестве своего класса. Вы все еще не можете на самом деле получить доступ к классу, потому что он не существует (и не будет, пока код не будет выполнен, что находится в середине происходящего прямо сейчас). Но если вы знаете, что имя никогда не будет переопределено, вы можете просто сохранить имя и посмотреть его позже (возможно, вам также понадобится f_locals['__module__']
, чтобы посмотреть его) во время вызова, чтобы получить класс.
Однако гораздо более приятным решением является создание декоратора класса и декоратора, который работает с ним. Хитрость заключается в том, что декораторы «регистрации» каким-то образом хотят, чтобы они (функции, которые они возвращают), «фиксировались». Затем декоратор класса выполняет итерацию через зарегистрированные методы и исправляет их.
Например:
def class_deco(cls):
for name, method in inspect.getmembers(cls, callable):
if hasattr(method, 'class_fixup'):
method.class_fixup(cls)
return cls
Теперь ваш метод декоратора все еще не может получить доступ к классу во время вызова, но он может создать функцию «FixUp», который заканчивает украшающие вещи, когда класс готов, то просто сделайте f.class_fixup = fixup
прямо перед тем return f
.
Есть ли причина, по которой вы используете классический класс вместо класса нового стиля? (И, если вы хотите классический класс, почему 'User()' вместо просто 'User'?) Это не влияет на ответ в этом случае, но почти везде, где он _does_ делает разницу, классический класс не то, что вы хотите. – abarnert
Между тем, 'u.method' - это функция _not_, это связанный метод. Если вы видите что-то еще, вы не используете тот же код, который вы нам показывали. И, поскольку функции не имеют классов, ваш вопрос бессмыслен. – abarnert
ОК, после редактирования ... Это совершенно другой вопрос. Декоратор не получает связанный метод 'u.method' или даже несвязанный метод' U.method', потому что 'U.method' не может быть создан до тех пор, пока не вернется декоратор. Он просто получает простую старую функцию. Поэтому вы не можете проверить его для класса. – abarnert