属性getter和上下文管理器

时间:2018-01-26 21:48:58

标签: python pandas properties decorator contextmanager

我想以这样的方式定义一个属性:无论何时调用它,它都是在上下文管理器中完成的。说,我从:

开始
res = some_function(self.hangar)

每当我写下代码时,

with pandas.HDFStore(...) as hangar:
    some_function(self.hangar)

我希望将其评估为:

{{1}}

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

接受的答案是正确的,但有类似的问题我选择创建一个属性,它也是一个上下文管理器。因此,我们的想法是将该属性用作上下文管理器始终

就你而言:

@property
def hangar(self):
    return pandas.HDFStore(...)

然后你使用with

with self.hangar as hangar:
   res = some_function(hangar)

这允许您为不是上下文管理器的内容更改 hangar 定义(例如在子类中)。在这种情况下,您需要装饰您的方法:

@property
@contextmanager
def hangar(self):
    yield self._hangar

它仍然有效。请记住,装饰器顺序很重要,因为 yield 而不是 return

答案 1 :(得分:0)

正如您从评论中看到的那样,您需要的内容与内容管理器的常用方式有些“内外”。

但是这并不能阻止你使你的函数调用/属性检索“内向外”完全相同:所有你需要的是,而不是使用'property'调用所需的方法,而是将目标函数作为参数传递。

有关此事:

def context_property(method):
    def wrapper(self, target, *args, **kw):
        path = method(self)
        with pandads.HDFStore(path) as context:
            result = target(context, *args, **kw)
        return result
    return wrapper

class MyClass:
    @context_property
    def hangar(self):
        return "path_to_hdfstore"

    def do_stuff(self):
        ...
        value = self.hangar(some_function)
        ...

some_function将在上下文管理器中运行。如果你需要使上下文管理器本身是通用的,而不是总是“pandas.HDFStore”,你可以在装饰器上再添加一个级别来配置它。