News for hackers. Stuff that matters.
Re:Why RAII rocks by czinck on Friday April 24, 2015 @08:49AM (#9432944)
you can do something like

    with a(b(c)) as f:
but then you risk any of those functions throwing an exception and screwing up the whole thing. You can move the resource allocation from __init__ to __enter__, but now you split your initialization code over 2 constructors. You can just hope and pray that a and b don't throw an exception, but someone is gonna accidentally break that assumption. And even if they don't, you've now spent more time worrying about that then if you just did manual memory allocation.

Or, in C++ you write

    class Foo {
    public:
        Foo() {/*get handle*/}
        ~Foo() {/*release resource*/}
    };
and you never have to worry again.
Re:Why RAII rocks by falcolas on Friday April 24, 2015 @09:40AM (#9433180)
> You can move the resource allocation from __init__ to __enter__, but now you split your initialization code over 2 constructors

After giving it some thought, I've come up with a better example which more closely maps to C++ RAII constructs, which shows that you don't need to split anything. Consider:

    class Shadow(object):
        def __init__(self):
            # Initialization code
        @classmethod
        def __enter__(cls, *args, **kwargs):
            return cls(*args, **kwargs)
        def __exit__(self, *args, **kwargs):
            # De-initialize
`__enter__` becomes three lines of boilerplate, which you could abstract out into an inheritable class, should you so desire.

As for "In C++ you write", it's the same as saying "in Python you write __enter__ and __exit__", but instead of instantiating via `std::unique_ptr` you use `with`.

Re:Why RAII rocks by czinck on Friday April 24, 2015 @11:50AM (#9434136)
Huh, neat. I'd seen @classmethod a few times but wasn't sure what it did. I need to see if I can refactor some code now.