Python 是否有访问函数的方法';是否在ContextDecorator中设置属性/参数?

Python 是否有访问函数的方法';是否在ContextDecorator中设置属性/参数?,python,python-3.x,python-decorators,contextmanager,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() # AttributeErr

我正在尝试使用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)

我翻遍了文件,没有发现任何有用的东西

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

编辑1: 正如@chepner在中所说的,ContextDecorator是

def func(dc, param1, param2):
    with savePen():
        ...
它无法访问函数的参数

但是,在这种情况下,使用savePen()在
中运行的任何程序都可以访问函数参数
dc
param1
param2
。这使我认为我应该能够使用ContextDecorator访问它们

例如,这是有效的:

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

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

请注意,使用
ContextDecorator
,上下文管理器的实例化没有参数,即

@savePen()
def func(dc, param1, param2):
    # do stuff, possibly changing the pen style
是语法糖(根据文档)吗


因此,没有办法告诉
savePen
要使用哪个对象(
dc
)。

我通过构建自己的装饰器来实现这一点,使用我以前在Python2中所做的东西

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

下面是我的想法(我已经删除了所有用于纠正文档字符串的绒毛):


这就是我害怕的。我想定义两个函数/类没什么大不了的,但如果只有一个就好了。我来试试,看看效果如何。谢谢如果ContextDecorator只是
def的语法糖。。。使用…
,它应该能够访问func的参数,对吗?更多细节请参见我的编辑
savePen
只能访问定义它的词法范围中的变量,而不能访问调用它的范围。(即使这样,您也需要Python3的
非本地
关键字来修改它们
@savePen()
def func(dc, param1, param2):
    # do stuff, possibly changing the pen style
def func(dc, param1, param2):
    with savePen():
        ...
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