【问题标题】:Property getter and context manager属性获取器和上下文管理器
【发布时间】:2018-07-06 07:21:18
【问题描述】:

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

@property
def hangar(self):
    return self._hangar

每当我写下代码时:

res = some_function(self.hangar)

我希望它被评估为:

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

有什么想法吗?

【问题讨论】:

  • 嗯,res 最终会成为什么?你不能把上下文管理器代码放在 getter 定义中吗?我不确定我是否理解你想要什么。
  • @juanpa.arrivillaga res 是某个函数在hangar 上运行的结果,但是hangar 需要在函数被调用之前打开并在之后立即关闭。
  • 您不能使用property 来做您想做的事情,因为getter 方法将在some_function 被调用之前完成运行。充其量你可以包装保持上下文活动的对象,直到它被垃圾收集,但确切的时间将非常不确定(它可能比你想要的存活时间更长)。如果您使用上下文管理器来确保清理某些内容,则应该明确并在适当的位置实际写出 with 语句。
  • @Blckknght 谢谢!我很害怕。

标签: python pandas properties decorator contextmanager


【解决方案1】:

正如您从 cmets 中看到的,您所需要的有点像上下文管理器通常的工作方式“由内而外”。

但这并不能阻止您使您的函数调用/属性检索“由内而外”完全一样:您所需要的只是,而不是使用“属性”调用所需的方法,而是将目标函数作为参数传递。

类似的东西:

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”,您可以在装饰器上再增加一层并进行配置。

【讨论】:

    【解决方案2】:

    接受的答案是正确的,但有类似的问题我选择创建一个也是上下文管理器的属性。所以想法是将属性用作上下文管理器总是

    在你的情况下:

    @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

    【讨论】:

      猜你喜欢
      • 2017-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-15
      • 2021-10-12
      相关资源
      最近更新 更多