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

2024-09-30 14:20:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用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

鉴于上述情况,这:

^{pr2}$

应等同于:

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

我在文档中搜寻了contextlib,没有发现任何有用的东西。在

有人知道如何从ContextDecorator类中访问修饰函数的属性吗?在

编辑1:

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

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

它不能访问函数的参数。在

但是,在本例中,with savePen()中运行的任何内容都可以访问函数参数dcparam1和{}。这使我认为我应该能够使用ContextDecorator访问它们。在

例如,这是有效的:

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

Tags: 函数self参数returndefwithdcparam1
2条回答

我用我以前在Python2中做过的东西,建造了自己的装饰工。在

我没有使用上下文管理器,而是使用了try...finally结构。在

以下是我的想法(我去掉了所有能使docstring正确的东西):

class savePen(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        """This provides support for functions """
        dc = args[0]
        prevPen = dc.GetPen()
        try:
            retval =  self.func(*args, **kwargs)
        finally:
            dc.SetPen(prevPen)
        return retval

    def __get__(self, obj, objtype):
        """ And this provides support for instance methods """
        @functools.wraps(self.func)
        def wrapper(*args, **kwargs):
            dc = args[0]
            prevPen = dc.GetPen()
            try:
                retval = self.func(obj, *args, **kwargs)
            finally:
                dc.SetPen(prevPen)
            return retval
        return wrapper

contextlib.contextmanager在这里似乎更合适。请注意,与其他任何东西一样,您不能从函数外部访问函数体的局部变量(无论如何,除了内省技巧之外)。在

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

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

注意,使用ContextDecorator,上下文管理器是不带参数的实例化的,即

^{pr2}$

语法糖(根据文档)是

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

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

相关问题 更多 >