I normally use this custom attr_as
context manager:
from contextlib import contextmanager
@contextmanager
def attr_as(obj, field:str, value) -> None:
old_value = getattr(obj, field)
setattr(obj, field, value)
yield
setattr(obj, field, old_value)
You can then use it with the exact same set of arguments you'd use for setattr
in attr_as
.
class Foo:
def __init__(self):
self.x = 1
foo = Foo()
with attr_as(foo, 'x', 2):
print(foo.x)
bar = 3
with attr_as(sys.modules[__name__], 'bar', 4):
print(bar)
Note, if you need to preserve the existence/nonexistence of the attribute rather than just the value, that's also possible with just a few more lines:
from contextlib import contextmanager
@contextmanager
def attr_as(obj, field:str, value) -> None:
old_exists = hasattr(obj, field)
if old_exists:
old_value = getattr(obj, field)
setattr(obj, field, value)
yield
if old_exists:
setattr(obj, field, old_value)
else:
delattr(obj, field)