Использование return в длинных операторах if-elseif-else (Python) - PullRequest
6 голосов
/ 23 июля 2011

Я использую 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 ]

11 голосов
/ 23 июля 2011

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

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

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

funs = {1: do_something_1,
        2: do_something_2,
        3: do_something_3}
funs[eggs]()
8 голосов
/ 23 июля 2011

Определенно не копировать идентичный код в каждое предложение 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() и т. Д. Происходит, только если яйца равны 1, 2 или 3.

3 голосов
/ 23 июля 2011

Как насчет:

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()
2 голосов
/ 23 июля 2011

Вы действительно уверены, что 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()

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

1 голос
/ 23 июля 2011

То, что вы делаете сейчас, не является плохой практикой программирования, но было бы плохой практикой дублировать код, помещая три вызова функций в каждый оператор 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
...