我有一个helper类Decontext
,我正使用它将上下文管理器转换为decorator(pyton2.6)。在
class Decontext(object):
"""
makes a context manager also act as decorator
"""
def __init__(self, context_manager):
self._cm = context_manager
def __enter__(self):
return self._cm.__enter__()
def __exit__(self, *args, **kwds):
return self._cm.__exit__(*args, **kwds)
def __call__(self, func):
def wrapper(*args, **kwds):
with self:
return func(*args, **kwds)
return wrapper
我的contextmanager
接受了一个参数,我正试图找出在使用这个修饰符时如何传递该参数?在
这就是我如何使用它,但失败了:
my_deco = Decontext(sample_t)
@my_deco(arg1='example')
def some_func()
print 'works'
编辑:
我希望Decontext
类在执行__call__
函数时传递上下文管理器中的所有*args
。在
示例:
decorator_example = Decontext(sample_t) // I don't want to pass in the argument here but when the decorator is created. How can I modify my class to make this enhancement
编辑2:
我期望的例子
my_deco = Decontext(sample_t)
@my_deco(arg1='example')
def some_func()
print 'works'
预期产量:
'example' // running and passing argument to context_manager
'works' // after yield executing some_func
您遇到的问题是您在
__init__
方法中设置的_cm
属性实际上并不是存储上下文管理器实例,而是存储上下文管理器的类型(或者可能是生成上下文管理器实例的工厂函数)。稍后需要调用类型或工厂以获取实例。在试试这个方法,它既适用于上下文管理器实例(假设它们不可调用)也适用于需要参数的上下文管理器类型:
在那里有一个相当愚蠢的嵌套层次,但这是你所需要的,因为你想称之为事物。下面是一个实际应用的例子:
^{pr2}$它将输出:
请注意,尝试使用
foo_deco_factory
作为上下文管理器是行不通的(类似于使用with foo
也不起作用)。只有使用上下文管理器实例(而不是类型或工厂)初始化了Decontext
实例,或者它已经被调用为具有适当参数的装饰器时,才能在该实例上使用上下文管理器协议。在如果您不需要decorator来充当上下文管理器,那么您可以很容易地将整个类转换为一个函数(其中
__call__
将成为一个额外的闭包级别,而不是一个方法):为了简化这种情况下的代码,我总是假设您传递的是上下文管理器工厂,而不是上下文管理器实例。在
如果我理解正确,你应该:
装饰者必须装饰一些东西(比如函数)。但是,你的类还有一些其他问题,但我不确定如何解决它们,因为它有点难以理解它应该做什么。在
我想以下就是你要找的。主要的关键是您不能将您想要的上下文管理器参数直接传递给您的
Decontext
类上的__call__
方法,所以我们使用一个helper函数来实现这一点。有可能有一种方法可以简化这一点(但我将把它留给读者作为练习:)该输出:
^{pr2}$相关问题 更多 >
编程相关推荐