【发布时间】:2019-05-09 14:18:23
【问题描述】:
我正在使用 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。但是,我想将CallableDecorator 中的foo 属性从bar 更改为在bar 函数中计算的值,但在定义bar 时未知。有没有办法访问这个?
我不是在问这是否是一个好的设计,或者何时有用,我只是想了解如何做到这一点。
【问题讨论】:
标签: python python-decorators callable contextmanager