I have my own context manager class: my_context_manager
, I want to convert the result to the giving output_type
, can be for example str
, list
, int
whatever, I tried to play with the __enter__
, __exit__
methods, in my_context_manager
, but I didn't find how to get the variable used inside the with scope,
with my_context_manager(output_type): # output_type can be str, int etc
result = 5 2 #( or any other any arithmetical operation operation)
CodePudding user response:
You can't manipulate the code running in the with
block with a context manager.
Basically all that with
does is call __enter__
and __exit__
on the object you with
, so your code is (if we skip exception handling) equivalent to
_anonymous_var = my_context_manager(output_type)
_anonymous_var.__enter__()
result = 5 2
_anonymous_var.__exit__()
EDIT
if we replaced the 5 and the 2 with a custom object, can i modify the result object to converted based on the giving type in the context manager?
You could return the custom object from the context manager, like so:
from contextlib import contextmanager
@contextmanager
def my_context_manager(output_type):
def caster(in_value):
out_value = output_type(in_value)
print(f"cast {in_value!r} to {out_value!r}")
return out_value
yield caster
with my_context_manager(int) as c:
result = c(5) c("2")
print(result)
with my_context_manager(str) as c:
result = c(5) c(2)
print(result)
The output is
cast 5 to 5
cast '2' to 2
7
cast 5 to '5'
cast 2 to '2'
52
but if you don't want to return a brand new thing, you can also just modify an existing object within the with
:
class MySpecialClass:
behavior = ...
@contextmanager
def behave_differently(behavior):
old_behavior = MySpecialClass.behavior
try:
MySpecialClass.behavior = behavior
yield
finally:
MySpecialClass.behavior = old_behavior
CodePudding user response:
well i solve it finally, the solution is to change the add sub methods of the operand, so if the context class has a type not None, will converted it to the giving type. otherwise it will remain the same.
class MyObject:
def __init__(self, value, ):
self.value = value
def __add__(self, other):
new_obj = MyObject(self.value other.value)
if MyContextManager.output_type is not None:
new_obj.conversion(my_context_manager.output_type)
return new_obj
def __sub__(self, other):
new_obj = MyObject(self.value other.value)
if MyContextManager.output_type is not None:
new_obj.conversion(my_context_manager.output_type)
return new_obj
def conversion(self, new_type):
pass
class MyContextManager:
output_type = None
def __init__(self, output_type):
self.output_type = output_type
def __enter__(self):
self.change_output(self.output_type)
def __exit__(self, exc_type, exc_val, exc_tb):
self.change_output(None)
@classmethod
def change_output(cls, output_type):
cls.output_type = output_type