Python 是否有访问函数的方法';是否在ContextDecorator中设置属性/参数?
我正在尝试使用Python的contextlib.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
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