Search code examples
pythonpython-3.xwith-statementraii

Hide post-function calls in with statement


I have a function f that returns two parameters. After this function, I use the first parameter. I need the second one to glue things together with another function g. So my code would look like:

a, b = f()
# do stuff with a
g(b)

This is very repetitive, so I figured I could use something like a RAII approach. But, since I don't know when objects will die and my main goal is to get rid of the repetitive code, I used the with statement:

with F() as a:
    # do stuff with a

That's it. I basically created an object F around this function, supplying __enter__ and __exit__ functions (and obviously __init__ function).

However, I still wonder whether this is the right "Pythonic" way to handle this, since a with statement was meant to handle exceptions. Especially this __exit__ function has three arguments, which I don't use at the moment.

Edit (further explanations): Whenever i call f() i NEED to do something with b. It does not matter what happened in between. I expressed it as g(b). And exactly this i hide away in the with statement. So the programmer doesn't have to type g(b) again and again after every call of f(), which might get very messy and confusing, since #do stuff with a might get lengthy.


Solution

  • A slightly more pythonic way of doing it would be to use the contextlib module. You can do away with rolling out your own class with __enter__ and __exit__ functions.

    from contextlib import contextmanager
    
    def g(x):
        print "printing g(..):", x
    
    def f():
        return "CORE", "extra"
    
    @contextmanager
    def wrap():
        a, b = f()
        try:
            yield a
        except Exception as e:
            print "Exception occurred", e
        finally:
            g(b)
    if __name__ == '__main__':
        with wrap() as x:
            print "printing f(..):", x
            raise Exception()
    

    Output:

    $ python temp.py
    printing f(..): CORE
    Exception occurred
    printing g(..): extra