У меня примерно следующее. В основном мне нужно получить доступ к классу метода экземпляра из декоратора, используемого для метода экземпляра в его определении.
def decorator(view):
# do something that requires view's class
print view.im_class
return view
class ModelA(object):
@decorator
def a_method(self):
# do some stuff
pass
Код как есть:
AttributeError: объект 'функция' не имеет атрибута 'im_class'
Я нашел аналогичный вопрос / ответы - декоратор Python заставляет функцию забыть, что он принадлежит классу, и класс Get в декораторе Python, но они полагаются на обходной путь, который захватывает экземпляр во время выполнения, выхватывая первый параметр. В моем случае я буду вызывать метод на основе информации, полученной из его класса, поэтому я не могу дождаться поступления вызова.
inspect.getmro(cls)
для обработки всех базовых классов в декораторе классов для поддержки наследования.inspect
на спасение stackoverflow.com/a/1911287/202168Начиная с python 3.6 вы можете использовать
object.__set_name__
для этого очень простой способ. ДоП утверждает , что__set_name__
является «в то время называли владеющий классом владелец создается». Вот пример:Обратите внимание, что он вызывается во время создания класса:
Если вы хотите узнать больше о том, как создаются классы и, в частности, когда именно они
__set_name__
вызываются, вы можете обратиться к документации «Создание объекта класса» .источник
@class_decorator('test', foo='bar')
def decorator(*args, **kwds): class Descriptor: ...; return Descriptor
__set_name__
хотя давно использую Python 3.6+.hello
это не метод, а объект типаclass_decorator
.if TYPE_CHECKING
для определенияclass_decorator
в качестве обычного декоратора, возвращающего правильный тип.Как указывали другие, класс не был создан во время вызова декоратора. Однако можно аннотировать объект функции с помощью параметров декоратора, а затем повторно декорировать функцию в
__new__
методе метакласса . Вам нужно будет получить доступ к__dict__
атрибуту функции напрямую, поскольку, по крайней мере, для меня этоfunc.foo = 1
привело к AttributeError.источник
setattr
следует использовать вместо доступа__dict__
Как предлагает Марк:
Этот код показывает, как это может работать с использованием автоматической постобработки:
На выходе получаем:
Обратите внимание, что в этом примере:
Надеюсь это поможет
источник
Как указали Муравьи, вы не можете получить ссылку на класс изнутри класса. Однако, если вы хотите различать разные классы (а не манипулировать фактическим объектом типа класса), вы можете передать строку для каждого класса. Вы также можете передать любые другие параметры декоратору, используя декораторы в стиле класса.
Печать:
Также см. Страницу Брюса Экеля о декораторах.
источник
@decorator('Bar')
в отличие от@Decorator('Bar')
.Что делает flask-classy , так это создает временный кеш, который он хранит в методе, а затем он использует что-то еще (тот факт, что Flask зарегистрирует классы с помощью
register
метода класса), чтобы фактически обернуть метод.Вы можете повторно использовать этот шаблон, на этот раз используя метакласс, чтобы вы могли обернуть метод во время импорта.
В реальном классе (вы можете сделать то же самое, используя метакласс):
Источник: https://github.com/apiguy/flask-classy/blob/master/flask_classy.py
источник
Проблема в том, что при вызове декоратора класс еще не существует. Попробуй это:
Эта программа выведет:
Как видите, вам придется придумать другой способ делать то, что вы хотите.
источник
Вот простой пример:
Результат:
источник
Это старый вопрос, но встретил венерианский. http://venusian.readthedocs.org/en/latest/
Кажется, у него есть возможность украшать методы и при этом предоставлять вам доступ как к классу, так и к методу. Обратите внимание, что призыв
setattr(ob, wrapped.__name__, decorated)
не является типичным способом использования венерианского языка и несколько противоречит цели.В любом случае ... приведенный ниже пример завершен и должен выполняться.
источник
Функция не знает, является ли это методом в точке определения, когда выполняется код декоратора. Только когда к нему обращаются через идентификатор класса / экземпляра, он может узнать свой класс / экземпляр. Чтобы преодолеть это ограничение, вы можете декорировать дескриптор объекта, чтобы отложить фактический код декорирования до времени доступа / вызова:
Это позволяет украсить отдельные (статические | классовые) методы:
Теперь вы можете использовать код декоратора для самоанализа ...
... и для изменения поведения функции:
источник
</sigh>
Как указывали другие ответы, декоратор - это функциональная вещь, вы не можете получить доступ к классу, к которому принадлежит этот метод, поскольку класс еще не был создан. Однако вполне нормально использовать декоратор, чтобы «пометить» функцию, а затем использовать методы метакласса для работы с методом позже, потому что на
__new__
этапе класс был создан с помощью своего метакласса.Вот простой пример:
Мы используем,
@field
чтобы пометить метод как специальное поле и работать с ним в метаклассе.источник
if inspect.isfunction(v) and getattr(k, "is_field", False):
она должна бытьgetattr(v, "is_field", False)
вместо нее .У вас будет доступ к классу объекта, для которого вызывается метод, в декорированном методе, который должен вернуть ваш декоратор. Вот так:
Вот что он делает с помощью вашего класса ModelA:
источник
Я просто хочу добавить свой пример, поскольку в нем есть все, что я мог придумать для доступа к классу из декорированного метода. Он использует дескриптор, как предлагает @tyrion. Декоратор может принимать аргументы и передавать их дескриптору. Он может иметь дело как с методом в классе, так и с функцией без класса.
источник