When is it advisable to use a ret_val variable?

coding-style, python, return-value

Solution

Did we forget why "multiple exit points" was considered harmful in the first place? Back in the day (before widespread access to good exception handling and finally constructs, or managing objects like `auto_ptr` that do cleanup when they leave scope), this was the problem that haunted many multi-exit functions:

int function blah(arg1, arg2)
    allocate resource

    if early failure detection
        return failure_status

    ... much later...

    release resource // oh rats! resource didn't release
    return success_status

If the resource is memory, this creates a memory leak. If it's a database transaction, we are heading for bad database contention or deadlock. For that matter, with the advent of more exception support, we implicitly add many potential exits from a method (by virtue of an unhandled exception). In my C++ days, I developed the habit of never calling delete, but instead using `auto_ptr`, so that allocated memory was cleaned up when the `auto_ptr` exited its scope, even if some unexpected exception reared its head.

In our garbage collected Python world, we can still have this issue, even though many of our objects, such as files, or locks, have improved self-cleaning behavior. But in implementations other than CPython (jython and IronPython to name two), there is no guarantee just when a destructor will get called, so something more proactive needs to be built into your method. The first mechanism for this purpose was try/finally:

int function blah(arg1, arg2)
    allocate resource
    try:

        if early failure detection
            return failure_status

        ... much later...
        return success_status

    finally:
        release resource // always releases no matter what

But now Python has context managers, in conjunction with the new 'with' syntax:

int function blah(arg1, arg2)
    allocate resource
    with context_manager(resource): // releases on exit from 'with'

        if early failure detection
            return failure_status

        ... much later...
        return success_status

So let's be sure that we tell the whole story, that the reason we can discard this old chestnut is that newer coding practices make it unnecessary.

Problem

I have seen conflicting advice on whether the following code is better ``` def function(): ret_val = 0 if some_condition(): ret_val = 2 else: ret_val = 3 return ret_val ``` or whether this is better: ``` def function(): if some_condition(): return 2 else: return 3 ``` This is a simple example, and I've written it in python-style, but what I'm looking for is a general principle as to when to use some "accumulator" variable to keep track of the return value, or whether to use multiple exit points. I know different languages might have different reasons for using one style over the other, so I'd appreciate differing viewpoints for why a particular language might stick with a particular style. (Specifically in the past I've heard that structured programming in C avoids having multiple exit points for a function.)

Original source

Related problems