Home > Software engineering >  convert the result in the context manager
convert the result in the context manager

Time:10-25

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
  • Related