我想使用装饰器deco
来重塑__enter__
和__exit__
实例方法。代码可以运行,但包装器在本with
节中未执行。请在下面找到实际输出,然后是预期输出,最后是代码。
电流输出:
In __init__
-------------------
In __enter__
-------------------
In wrapper
Blah, blah, blah
-------------------
In __exit__
预期输出:
In __init__
-------------------
In wrapper
In __enter__
-------------------
In wrapper
Blah, blah, blah
-------------------
In wrapper
In __exit__
class contMgr():
def __init__(self):
print("In __init__")
pass
def __enter__(self):
print("In __enter__")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("In __exit__")
pass
def __call__(self, *args, **kwargs):
print("In __call_")
def brol():
print("brol")
def deco(func):
def wrapper(*args,**kwargs):
print("In wrapper")
result = func(*args, **kwargs)
return result
return wrapper
@deco
def test():
print("Blah, blah, blah")
mgr = contMgr()
mgr.__enter__ = deco(mgr.__enter__)
mgr.__exit__ = deco(mgr.__exit__)
print("------------------------")
with mgr:
print("------------------------")
test()
print("------------------------")
简短的答案
正如其他人指出的那样,问题在于将调用类的
__enter__
和方法,而不是实例的方法。__exit__
但是您说这是为了测试目的,并且您不希望装饰器永久存在,所以解决方案是暂时改变类方法。
当然,您可以手动完成此操作:更改类上的函数,运行测试,然后将其改回来,但
unittest.mock.patch
可以为您自动完成此操作。使用补丁
下面介绍了如何使用
patch
上下文管理器,一旦离开上下文管理器的范围,它将恢复原始功能:将仅在此 with 语句内部调用修饰的 enter 和 exit。
下面是一个带有输出的更长的例子:
输出:
文档
https://docs.python.org/3/library/unittest.mock.html#patch