我有一个测试类,需要在最后进行一些清理。为了确保用户不会忘记这样做,我想在课程中添加一个上下文管理器。我还有一个装饰器,我想在其中使用此上下文管理器来创建测试类的对象并将其传递给装饰函数。它甚至可能吗?
这就是我要做的事情:
class test:
def __init__(self, name):
self._name = name
print "my name is {0}".format(name)
def exit():
print "exiting"
@contextmanager
def testcm(self):
print "inside cm"
try:
yield self
finally:
self.exit()
def randomtest(self, str):
print "Inside random test {0}".format(str)
def decorate(name):
def wrapper(testf):
def testf_wrapper(test):
with test(name).testcm() as testobj:
return testf(testobj)
return testf_wrapper
return wrapper
return decorate
@decorate("whatever")
def testf(testobj):
testobj.randomtest("randomness")
函数testf
接受测试类对象 - testobj
并对其进行处理。之后,由于上下文管理器,testcm
确保调用清理函数。
所以有两个问题:
如何在装饰器中使用上下文管理器,我知道装饰器必须返回一个函数,但是如果我返回该函数(如上面的代码所示),上下文管理器将如何调用清理?
如何将装饰器中创建的对象传递给装饰函数,如果我像上面的代码一样传递它,我将如何调用装饰函数?
答案 0 :(得分:5)
您的示例程序中有几个错误,我在所有test
/ testf
/ testobj
冗余中丢失了。请允许我直接解答您的问题。
如何在装饰器中使用上下文管理器?
正如您在其他任何地方使用上下文管理器一样。考虑这个程序,它使用装饰器在调用函数时透明地将str
转换为file
:
def opener(func):
def wrapper(name):
with open(name) as input_file:
func(input_file)
return wrapper
@opener
def first_line(fd):
print fd.readline()
first_line('/etc/passwd')
如您所见,装饰器函数使用围绕调用函数调用的上下文管理器。
如何将在decorator中创建的对象传递给装饰函数,如果我像上面的代码一样传递它,我将如何调用装饰函数?
正如您将对象传递给任何函数一样。见上面的例子。装饰器创建一个file
对象并将其传递给装饰函数。
为了完整性,以下是修复错误的示例程序:
from contextlib import contextmanager
class test:
def __init__(self, name):
self._name = name
print "my name is {0}".format(name)
def exit(self):
print "exiting"
@contextmanager
def testcm(self):
print "inside cm"
try:
yield self
finally:
self.exit()
def randomtest(self, str):
print "Inside random test {0}".format(str)
def decorate(name):
def wrapper(testf):
def testf_wrapper():
with test(name).testcm() as testobj:
return testf(testobj)
return testf_wrapper
return wrapper
@decorate("whatever")
def testf(testobj):
testobj.randomtest("randomness")
testf()