Использование return в длинных операторах if-elseif-else (Python)

Я использую Python для своего примера, но мой вопрос относится к языкам программирования в целом.

def some_function(eggs):
    if eggs == 1:
        do_something_1()
    elif eggs == 2:
        do_something_2()
    elif eggs == 3:
        do_something_3()
    else:
        do_error()
        return
    do_something_4()
    do_something_5()
    do_something_6()

(Это всего лишь пример. Мои функции не будут называться do_something_x.)

будет ли возврат в другое, как это, плохой практикой программирования? Было бы лучше поставить

do_something_4()
do_something_5()
do_something_6()

в каждом из if / elifs?

5 ответов


основная проблема, которую я вижу с вашим кодом, заключается в том, что случай ошибки скрыт более чем на полпути вниз по телу функции. Это затрудняет чтение кода. Поскольку то, что вы делаете, проверяет аргументы функции, вы должны сделать это в первую очередь.

мое предпочтение в случае недопустимого аргумента-вызвать соответствующее исключение, такое как ValueError. Не зная, что делает ваша функция, или что do_error нет, трудно сказать с абсолютной уверенностью, что это касается к вашему делу. Но, как правило, получение неправильных аргументов не является тем, от чего функция может восстановиться. Вызывающий дал аргументы; поэтому возложите бремя на вызывающего, чтобы оправиться от этой ошибки.

кроме того, вот идиома, которую вы можете использовать, чтобы избежать длинных списков elifs:

funs = {1: do_something_1,
        2: do_something_2,
        3: do_something_3}
funs[eggs]()

наверняка не скопируйте идентичный код в каждый if предложения.

как насчет:

def some_function(eggs):
    options = {1: do_something_1, 2: do_something_2, 3: do_something_3}
    if eggs in options: 
        options[eggs]()
        do_something_4()
        do_something_5()
        do_something_6()
    else:
        do_error()
        return

это не требует долгого if elif else. Это также ясно do_something_4() etc. только если яйца 1, 2 или 3.


Как насчет:

def some_function(eggs):
    if eggs not in [1,2,3]:
        do_error()
        return

    if eggs == 1:
        do_something_1()
    elif eggs == 2:
        do_something_2()
    elif eggs == 3:
        do_something_3()
    else:
        assert False
    do_something_4()
    do_something_5()
    do_something_6()

вы действительно уверены, что do_something_n действительно связано с do_something_m?

если это так, используйте do_something(var, n) и использовать один и тот же код для всего с несколькими if (в конце концов, концепция действительно связана, не так ли?).

если нет, разделите функции на действительно полезные и автономные функции.


пример, почему это (наверное) плохо:

def print1():
    print(1)

def print2():
    print(2)

Ну, кто-то должен видеть, что это должно быть printn(n) или что-то подобное.

и другие вероятность:

def action1():
    paymanagers()
    payworkers()

def action2():
    clean_trashbin()
    unlock_car()

эти действия, вероятно, не связаны и должны принадлежать к их собственным функциям.


то, что вы делаете сейчас, не плохая практика программирования, но было бы плохой практикой дублировать код, помещая три вызова функций в каждый if заявление.

некоторые люди предпочитают иметь одну точку выхода к их функциям, в этом случае я бы предложил что-то вроде этого:

def some_function(eggs):
    error_code = 0
    if eggs == 1:
        do_something_1()
    elif eggs == 2:
        do_something_2()
    elif eggs == 3:
        do_something_3()
    else:
        do_error()
        error_code = 1

    if error_code == 0:
        do_something_4()
        do_something_5()
        do_something_6()
    return   # return error_code if it would be helpful to the calling function