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

dth*_*hor 6 python contextmanager python-3.x python-decorators

我正在尝试使用 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
Run Code Online (Sandbox Code Playgroud)

鉴于上述,这:

@savePen()
def func(dc, param1, param2):
    # do stuff, possibly changing the pen style
Run Code Online (Sandbox Code Playgroud)

应该相当于:

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

我已经冲刷的文档contextlib并没有发现任何有用的东西。

有谁知道如何从 ContextDecorator 类中访问装饰函数的属性?

编辑1:

正如@chepner 在此回复中所说,ContextDecorator 是糖

def func(dc, param1, param2):
    with savePen():
        ...
Run Code Online (Sandbox Code Playgroud)

并且它不能访问函数的参数。

然而,在这种情况下,任何的内部运行with savePen()访问函数的参数dcparam1param2。这让我觉得我应该能够使用 ContextDecorator 访问它们。

例如,这是有效的:

def func(dc, param1, param2):
    with savePen():
        print(param1)
Run Code Online (Sandbox Code Playgroud)

che*_*ner 1

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

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

with savePen(dc):
    func(dc, param1, param2)
Run Code Online (Sandbox Code Playgroud)

请注意,使用 a 时ContextDecorator,上下文管理器是在不带参数的情况下实例化的,即

@savePen()
def func(dc, param1, param2):
    # do stuff, possibly changing the pen style
Run Code Online (Sandbox Code Playgroud)

是语法糖(根据文档)

def func(dc, param1, param2):
    with savePen():
        ...
Run Code Online (Sandbox Code Playgroud)

因此无法判断要使用savePen哪个对象 ( )。dc