In python, there are many functions that work as both standard functions and context managers. For example open() can be called either as:
my_file=open(filename,'w')
or
with open(filename,'w') as my_file:
Both giving you a my_file object that can be used to do whatever you need to. In general the later is preferable, but there are times when one might want to do the former as well.
I've been able to figure out how to write a context manager, either by creating a class with __enter__ and __exit__ functions or by using the @contextlib.contextmanager decorator on a function and yield rather than return. However, when I do this I can no longer use the function straight - using the decorator, for example, I get a _GeneratorContextManager object back rather than the result that wanted. Of course, if I made it as a class, I'd just get an instance of the generator class, which I'd assume is essentially the same thing.
So how can I design a function (or class) that works as either a function, returning an object, or a context manager, returning a _GeneratorContextManager or the like?
edit:
For example, say I have a function like the following (this is HIGHLY simplified):
def my_func(arg_1,arg_2):
result=arg_1+arg_2
return my_class(result)
So the function takes a number of arguments, does stuff with them, and uses the result of that stuff to initialize a class, which it then returns. End result is I have an instance of my_class, just like I would have a file object if I had called open. If I want to be able to use this function as a context manager, I can modify it like so:
@contextlib.contextmanager
def my_func(arg_1,arg_2):
result=arg_1+arg_2 # This is roughly equivalent to the __enter__ function
yield my_class(result)
<do some other stuff here> # This is roughly equivalent to the __exit__function
Which works just fine when calling as a context manager, but I no longer get an instance of my_class when calling as a straight function. Perhaps I'm just doing something wrong?
Edit 2:
Note that I do have full control over my_class, including the ability to add functions to it. From the accepted answer below, I was able to infer that my difficulty stemmed from a basic misunderstanding: I was thinking that whatever I called (my_func in the example above) needed to have the __exit__ and __enter__ functions. This is not correct. In fact, it's only what the function returns (my_class in the above example) that needs the functions in order to work as a context manager.