有没有办法在ContextDecorator中访问函数的属性/参数?

时间:2015-07-30 18:42:11

标签: python python-3.x python-decorators contextmanager

我尝试使用Python的contextlib.ContextDecorator类编写上下文管理器装饰器。

有没有办法在上下文管理器中访问已修饰函数的参数?

以下是我正在做的事情的一个例子:

from contextlib import ContextDecorator

class savePen(ContextDecorator):
    def __enter__(self):
        self.prevPen = self.dc.GetPen()     # AttributeError
        return self

    def __exit__(self, *exc):
        self.dc.SetPen(self.prevPen)
        return False

鉴于上述情况,这个:

@savePen()
def func(dc, param1, param2):
    # do stuff, possibly changing the pen style

应该相当于:

def func(dc, param1, param2):
    prevPen = dc.GetPen()
    # do stuff, possibly changing the pen style
    dc.SetPen(prevPen)

我已经搜索了contextlib的文档并且找不到任何有用的内容。

有谁知道如何访问装饰功能' ContextDecorator类中的属性?

EDIT1:

正如@chepner在this response中所说,ContextDecorator是

的糖
def func(dc, param1, param2):
    with savePen():
        ...

并且它无法访问功能'参数。

但是,在这种情况下,with savePen()内的任何内容都可以访问函数参数dcparam1param2。这让我觉得我应该能够使用ContextDecorator访问它们。

例如,这是有效的:

def func(dc, param1, param2):
    with savePen():
        print(param1)

2 个答案:

答案 0 :(得分:1)

contextlib.contextmanager似乎更合适。请注意,与其他任何内容一样,您无法从函数外部访问函数体的局部变量(无论如何都缺少内省黑客)。

@contextlib.contextmanager
def savePen(dc):
    prevPen = dc.GetPen()
    yield
    dc.SetPen(prevPen)

with savePen(dc):
    func(dc, param1, param2)

请注意,对于ContextDecorator,上下文管理器实例化时不带参数,即

@savePen()
def func(dc, param1, param2):
    # do stuff, possibly changing the pen style

的语法糖(根据文档)
def func(dc, param1, param2):
    with savePen():
        ...

所以没有办法告诉savePen使用哪个对象(dc)。

答案 1 :(得分:0)

我设法通过构建自己的装饰器,使用我之前在Python2中完成的东西来做到这一点。

我没有使用上下文管理器,只使用了this结构。

这就是我提出的问题(我已经删除了使文档字符串正确的所有漏洞):

try...finally