可以使用class的方法作为contextmanager吗?
Is it okay to use the method of a class as contextmanager?
所以,这是一个简单的代码:
from contextlib import contextmanager
class A:
def __init__(self):
self.a = 1
return
@contextmanager
def a2mode(self):
self.a = 2
print(self.a)
yield
self.a = 1
print(self.a)
return
ca = A()
with ca.a2mode() as cm:
print(ca.a+1)
打印:
2
3
1
基本上,我使用 class 的方法来创建一个上下文,其中属性 a 的值为 a=2,而不是其通常的值。基于此执行一些操作,这些操作使用 a 的修改值。在该上下文中操作后,该属性在上下文管理器之前重置为其原始值。
这样做可以吗,还是会导致一些不可预见的问题?它有效,但我不确定这是否是“禁止”代码。
谢谢!
最好的,JZ
那应该没问题,但如果你想确保 a
即使 context-managed 块加注也能重置,你需要使用 try: finally:
.
@contextmanager
def a2mode(self):
self.a = 2
try:
yield
finally:
self.a = 1
此外,如果有更多模式,您需要确保重置为之前的模式...
@contextmanager
def a2mode(self):
old_a = self.a
self.a = 2
try:
yield
finally:
self.a = old_a
明确定义 __enter__
和 __exit__
可能更简单,因为 __exit__
接收在 with
语句中引发的任何异常作为参数。
class A:
def __init__(self):
self.a = 1
return
def __enter__(self):
self.a = 2
print(self.a)
def __exit__(self, *args):
self.a = 1
print(self.a)
# I don't know the most idiomatic way of checking this...
if args != (None, None, None):
exc_type, exc_value, traceback = args
...
# Return a true value to prevent the exception from propagating
所以,这是一个简单的代码:
from contextlib import contextmanager
class A:
def __init__(self):
self.a = 1
return
@contextmanager
def a2mode(self):
self.a = 2
print(self.a)
yield
self.a = 1
print(self.a)
return
ca = A()
with ca.a2mode() as cm:
print(ca.a+1)
打印:
2
3
1
基本上,我使用 class 的方法来创建一个上下文,其中属性 a 的值为 a=2,而不是其通常的值。基于此执行一些操作,这些操作使用 a 的修改值。在该上下文中操作后,该属性在上下文管理器之前重置为其原始值。
这样做可以吗,还是会导致一些不可预见的问题?它有效,但我不确定这是否是“禁止”代码。
谢谢! 最好的,JZ
那应该没问题,但如果你想确保 a
即使 context-managed 块加注也能重置,你需要使用 try: finally:
.
@contextmanager
def a2mode(self):
self.a = 2
try:
yield
finally:
self.a = 1
此外,如果有更多模式,您需要确保重置为之前的模式...
@contextmanager
def a2mode(self):
old_a = self.a
self.a = 2
try:
yield
finally:
self.a = old_a
明确定义 __enter__
和 __exit__
可能更简单,因为 __exit__
接收在 with
语句中引发的任何异常作为参数。
class A:
def __init__(self):
self.a = 1
return
def __enter__(self):
self.a = 2
print(self.a)
def __exit__(self, *args):
self.a = 1
print(self.a)
# I don't know the most idiomatic way of checking this...
if args != (None, None, None):
exc_type, exc_value, traceback = args
...
# Return a true value to prevent the exception from propagating