When is it appropriate to use the ret_val variable?

I saw conflicting tips 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 is it better:

def function():
    if some_condition():
        return 2
    else:
        return 3

This is a simple example, and I wrote it in python style, but what I'm looking for is a general principle when you should use some โ€œbatteryโ€ variable to track the return value or use multiple exit points. I know that different languages โ€‹โ€‹can have different reasons for using one style over another, so I would appreciate different points of view why a particular language can adhere to a certain style. (In particular, in the past I heard that structured C programming avoids having multiple exit points for a function.)

+3
11

, " " ? ( , , , auto_ptr, ), , :

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

, . , . ( ). ++ delete, auto_ptr, , auto_ptr , .

, Python, , , , . , CPython (jython IronPython, ), , , - . 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

Python "":

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

, , , , , .

+8

Python - , .

def function():
    if some_condition():
        return 2
    return 3

.. else, if .

+5

, . , . , .

, , C .

- , (, " " ).

+5

, :

>>> def foo():
...     r = 0
...     if bar():
...             r = 2
...     else:
...             r = 3
...     return r
... 
>>> dis.dis(foo)
  2           0 LOAD_CONST               1 (0)
              3 STORE_FAST               0 (r)

  3           6 LOAD_GLOBAL              0 (bar)
              9 CALL_FUNCTION            0
             12 JUMP_IF_FALSE           10 (to 25)
             15 POP_TOP             

  4          16 LOAD_CONST               2 (2)
             19 STORE_FAST               0 (r)
             22 JUMP_FORWARD             7 (to 32)
        >>   25 POP_TOP             

  6          26 LOAD_CONST               3 (3)
             29 STORE_FAST               0 (r)

  7     >>   32 LOAD_FAST                0 (r)
             35 RETURN_VALUE        

14 - ...

>>> def quux():
...     if bar():
...             return 2
...     else:
...             return 3
... 
>>> dis.dis(quux)
  2           0 LOAD_GLOBAL              0 (bar)
              3 CALL_FUNCTION            0
              6 JUMP_IF_FALSE            5 (to 14)
              9 POP_TOP             

  3          10 LOAD_CONST               1 (2)
             13 RETURN_VALUE        
        >>   14 POP_TOP             

  5          15 LOAD_CONST               2 (3)
             18 RETURN_VALUE        
             19 LOAD_CONST               0 (None)
             22 RETURN_VALUE        

11 ...

, :

>>> def baz():
...     if bar():
...             return 2
...     return 3
... 
>>> dis.dis(baz)
  2           0 LOAD_GLOBAL              0 (bar)
              3 CALL_FUNCTION            0
              6 JUMP_IF_FALSE            5 (to 14)
              9 POP_TOP             

  3          10 LOAD_CONST               1 (2)
             13 RETURN_VALUE        
        >>   14 POP_TOP             

  4          15 LOAD_CONST               2 (3)
             18 RETURN_VALUE        

. , timeit, bar :

$ sudo nice -n -19 python b.py
('foo', 1.3846859931945801)
('quux', 1.282526969909668)
('baz', 1.2973799705505371)
$ sudo nice -n -19 python b.py
('foo', 1.354640007019043)
('quux', 1.2609632015228271)
('baz', 1.2767179012298584)

$ sudo nice -n -19 python3 b.py
foo 1.72521305084
quux 1.62322306633
baz 1.62547206879
$ sudo nice -n -19 python3 b.py
foo 1.73264288902
quux 1.67029309273
baz 1.62204194069

quux baz , , foo.

, , , , .

+2

, , , . , , , .

+1

, . , , . , . , , , , .

: (25 ), . , , .

+1

Python ( 2.6?) - , :

def function():
    return (2 if some_condition() else 3)

.

+1

. , ++ ( C, - ), , . :

Foo someFunction()
{
    Foo result(5);
    if (someConditionA())  return result;
    else if (someConditionB()) result.doSomething();
    result.doSomethingElse();
    return result;
}

, ( ):

Foo someFunction()
{
   if (someConditionA()) return Foo(5);
   if (someConditionB()) { Foo result(5); result.doSomething(); result.doSomethingElse(); return result; }
   Foo result(5);
   result.doSomethingElse();
   return result;
}

. , .

+1

, . , , .

+1

, ++ Java, , - , . Python, , None. return ret_val Python. , , , .

0

The return values โ€‹โ€‹are not directly scary for small functions like your example. However, if you have a large or complex function, then multiple return points may be more difficult to debug. If you have a coding standard, I would call it (here the variable is preferred in accordance with our coding standard of our company).

0
source

Source: https://habr.com/ru/post/1718749/


All Articles