Pythoni c способ условного возврата в функцию - PullRequest
2 голосов
/ 10 марта 2020

У меня есть пара функций, которые возвращают либо число, либо None. Я хочу, чтобы моя функция-обертка возвращала первый результат, который не является None. Есть ли другой способ сделать это, кроме как следующим образом?

def func1():
    return None
def func2():
    return 3
def func3():
    return None

def wrapper():
    result = func1()
    if result is not None:
        return result
    result = func2()
    if result is not None:
        return result
    result = func3()
    if result is not None:
        return result

Мне известно о return func1() or alternative; который возвращает результат func1(), если он не равен None, тогда возвращается alternative. В наиболее оптимальной ситуации я делаю что-то вроде (псевдокод):

return func1() or continue
return func2() or continue
return func3() or continue

Ответы [ 4 ]

4 голосов
/ 10 марта 2020

Вам понадобится al oop, который вернет первое не- None найденное значение.

def wrapper():
    for f in [func1, func2, func3]:
        result = f()
        if result is not None:
            return result

Если каждая функция вернет None, wrapper также будет достигать конца тела без явного return.

Немного укорочено в Python 3.8 или позже,

def wrapper():
    for f in [func1, func2, func3]:
        if (result := f()) is not None:
            return result

Вы также можете использовать функцию any:

def wrapper():
    if any((result := f()) is not None for f in [func1, func2, func3]):
        return result

(Я предпочитаю явный цикл; YMMV.)

2 голосов
/ 10 марта 2020

Если есть только три функции, и вы не заботитесь о том, чтобы отличить None от других значений Falsey, вы можете использовать

return func1() or func2() or func3()

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

return next(x for x in (f() for f in funcs) if x is not None)

Если вы хотите справиться со всеми вашими функциями, возвращающими None, вы можете добавить значение по умолчанию для next, например,

return next((x for x in (f() for f in funcs) if x is not None), None)
1 голос
/ 10 марта 2020

Вы можете комбинировать карту, фильтр и следующее:

def func1():
    print("executed func1()")
    return None
def func2():
    print("executed func2()")
    return 3
def func3():
    print("executed func3()")
    return None

functions = (func1,func2,func3)
call      = lambda f:f()
result    = next(filter(None,map(call,functions)),None)

print("result:",result)

вывод:

executed func1()
executed func2()
result 3

fun c 3 не выполняется

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

def func1(p1):
    print(f"executed func1({p1})")
    return None
def func2(p2a,p2b):
    print(f"executed func2{(p2a,p2b)}")
    return 3
def func3(p3):
    print(f"executed func3({p3})")
    return None

functions = [
               lambda: func1(10),
               lambda: func2("X",99),
               lambda: func3(3.5)
            ]
call      = lambda f:f()
result    = next(filter(None,map(call,functions)),None)

print(result)

output:

executed func1(10)
executed func2('X', 99)
3
0 голосов
/ 10 марта 2020

Вы можете сделать это:

def wrapper():
    functions = [func1, func2, func3]
    return next(filter(lambda result: result is not None,
                       f() for f in functions),
                None)

Возвращает None, если все функции возвращают None.

...