有没有办法在 ContextDecorator 中访问函数的 attributes/parameters?
Is there a way to access a function's attributes/parameters within a ContextDecorator?
我正在尝试使用 Python 的 contextlib.ContextDecorator class.
编写上下文管理器装饰器
有没有办法在上下文管理器中访问装饰函数的参数?
这是我正在做的一个例子:
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 class 中访问装饰函数的属性?
编辑 1:
正如@chepner 在 中所说,ContextDecorator 是
的糖
def func(dc, param1, param2):
with savePen():
...
并且它无法访问函数的参数。
但是,在这种情况下,在 with savePen()
内部运行的任何内容都可以访问函数参数 dc
、param1
和 param2
。这让我觉得我应该能够使用 ContextDecorator 访问它们。
例如,这是有效的:
def func(dc, param1, param2):
with savePen():
print(param1)
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
)。
我设法通过构建自己的装饰器来做到这一点,使用我之前在 Python2 中完成的东西。
我没有使用上下文管理器,而是使用了 try...finally
结构。
这是我想出的(我已经删除了所有做诸如使文档字符串正确的事情的绒毛):
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
我正在尝试使用 Python 的 contextlib.ContextDecorator class.
编写上下文管理器装饰器有没有办法在上下文管理器中访问装饰函数的参数?
这是我正在做的一个例子:
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 class 中访问装饰函数的属性?
编辑 1:
正如@chepner 在
def func(dc, param1, param2):
with savePen():
...
并且它无法访问函数的参数。
但是,在这种情况下,在 with savePen()
内部运行的任何内容都可以访问函数参数 dc
、param1
和 param2
。这让我觉得我应该能够使用 ContextDecorator 访问它们。
例如,这是有效的:
def func(dc, param1, param2):
with savePen():
print(param1)
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
)。
我设法通过构建自己的装饰器来做到这一点,使用我之前在 Python2 中完成的东西。
我没有使用上下文管理器,而是使用了 try...finally
结构。
这是我想出的(我已经删除了所有做诸如使文档字符串正确的事情的绒毛):
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