Я играю с менеджерами контекста и декораторами в Python и создал вызываемый класс декоратора менеджера контекста.У меня это украшает функцию, где я хочу изменить атрибут в классе декоратора.Вот простая версия класса декоратора:
class CallableDecorator:
def __init__(self):
print('Creating decorator')
self.foo = None
def __enter__(self):
print('Entering Decorator')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print(f'Exiting Decorator with attribute foo = {self.foo}')
def __call__(self, func):
print('Starting the call in Decorator')
@wraps(func)
def wrapper(*args, **kwargs):
with self:
print('In wrapped context manager')
return func(*args, **kwargs)
print('About to finish call in Decorator')
return wrapper
Затем я обертываю функцию, подобную
@CallableDecorator()
def bar():
something = do_stuff()
setattr(callable_decorator, 'foo', something)
print('bar')
, и она сразу напечатает
Creating decorator
Starting the call in Decorator
About to finish call in Decorator
, потому чтоэто в значительной степени вызывает CallableDecorator()bar()
, поэтому при создании этой функции создается объект типа CallableDecorator
.После вызова bar()
это печатается:
Entering Decorator
In wrapped context manager
bar
Exiting Decorator with foo = None
Что также ожидается, потому что теперь я звоню wrapper
.Однако я хочу изменить атрибут foo
в CallableDecorator
с bar
на значение, которое вычисляется в функции bar
, но неизвестно на момент определения bar
.Есть ли какой-нибудь доступ к этому?
Я не спрашиваю, хороший ли это дизайн или когда это когда-нибудь пригодится, я просто пытаюсь понять, как это сделать.