Is it a good practice to use a one time loop to simulate goto in python?

时间:2018-04-20 00:46:51

标签: python loops goto

goto is usually considered evil and are discouraged to be used. But sometimes goto gives a clearer and more readable organization of the code, for example: I want to do some step by step computation, where the result of each step determines whether the following steps are needed, and if needed, which branch to go. The logic itself is a bit complicated, so there are couple of nested if statements. Assuming goto was available in python, a neat way to achieve this would be:

do_something 
if ...:
    goto zero
do_something
if case 1:
    do_something
    if ...:
        goto zero
    do_something
elif case 2:
    do_something
    if ...:
        goto zero
    do_something
....
result = compute_result(....)
goto next

zero:
result = 0

next:
do_something

Without the help of goto, it is possible to get the same behavior by introducing boolean variables to store flags and add additional if tests to turn on or off codes. But this way makes the control flow much less readable. One workaround would be to abuse a one time for loop to simulate the goto version of the above code, like below:

zero = True
for _ in range(1):
    do_something 
    if ...:
        break
    do_something
    if case 1:
        do_something
        if ...:
            break
        do_something
    elif case 2:
        do_something
        if ...:
            break
        do_something
    ....
    zero = False

if zero:
    result = 0
else
    result = compute_result(....)

do_something

My question is, is this the best approach to write a more readable code?

2 个答案:

答案 0 :(得分:2)

An easy way to break out of a calculation early is to use an exception:

class ExitCalculation(Exception): pass

try:
    do_something
    if time_to_goto_zero:
        raise ExitCalculation()
    do_something
    if ...:
        do_something
        if time_to_go_to_zero:
            raise ExitCalculation()
    result = compute_result()
except ExitCalculation:
    result = 0

do next thing

答案 1 :(得分:2)

Exceptions provide the same type of structured jumps without the implication of repeated execution:

class Foo(Exception):
    pass

try:
    do_something
    if ...:
        raise Foo
    do_something
    if case_1:
        do_something
        if ...:
            raise Foo
        do_something
    elif case_2:
        do_something
        if ...:
            raise Foo
        do_something
except Foo:
    result = 0
else:
    result = compute_result(...)

Which exception(s) you use are a matter of why your "gotos" break the regular control flow.