在Python中,如何以最优雅的方式条件性地返回一个函数

4 投票
4 回答
989 浏览
提问于 2025-04-18 13:27

假设我有两个函数。我希望func2返回func1的结果,除非func1返回的是None,这种情况下func2就返回其他东西。我有两种方法可以做到这一点,但这两种方法我都觉得有点不太对劲。

我可以这样写:

def func1(n):
    if (condition):
        return foo

def func2(n):
    if func1(n) is not None:
        return func1(n)
    else:
        return something_else

但这样感觉不太好,因为我得调用func1(n)两次(而且func1(n)的计算量比较大)。为了避免这个问题,我可以这样写:

def func1(n):
    if (condition):
        return foo

def func2(n):
    foo = func1(n)
    if foo is not None:
        return foo
    else:
        return something_else

但这样也不太对,因为我觉得不应该为了检查func1是否返回None而创建一个永远不会再用的新变量。

有没有更简单的方法,可以让我不必调用func1两次,也不需要创建新变量?如果这真的是唯一的方法,你会推荐哪一种?我现在用的是第二种方法(先把func1的返回值赋给foo,然后返回foo,除非foo等于None)。

另外,请记住在我的实际代码中,我会调用几个不同的函数,我想返回第一个不是None的结果,这只是一个更简单的代码版本,用来说明我的问题。

4 个回答

1

你绝对不想让 func1 被调用两次——这样不仅效率低下,而且 func1 可能会有一些副作用,或者根据当时的状态返回稍微不同的结果。

另外,在 return 之后加 else 是没有必要的,因为 return 已经让函数结束了。

你第二个选项的改进版本可以是:

def func1(n):
    if condition:
        return foo

def func2(n):
    foo = func1(n)
    if foo is None:
        return something_else
    return foo

注意,这样做即使 func1 返回一个假值也能正常工作。

另外,考虑到 func1 的内容,你能这样做吗:

def func1(n):
    return foo

def func2(n):
    foo = func1(n)
    if condition:
        return foo
    return something_else

这要看 func1 的具体内容是什么。

1

这是我之前回答的一个完全不同的看法,基于你对iCodez的评论:

def func1(n):
    return ham

def func2(n):
    return jam

def func3(n):
    return spam

def mainfunc(n):
    for f in (func1, func2, func3):
        foo = f(n)
        if foo is not None:
            return foo
9

因为 None 的值是 False,所以你可以这样做:

def func2(n):
    return func1(n) or something_else

不过需要注意的是,如果 func1(n) 返回的是任何“假”的值(比如 0[] 等),那么 func2 会返回 something_else


对于很多函数,你可以使用 next 和一些 生成器表达式

def myfunc(n):
    vals = (f(n) for f in (func1, func2, func3...))
    return next((v for v in vals if v is not None), something_else)
6

给调用func1的结果起个名字是比较简单的,所以我会这么做,但函数可以这样写:

def func2(n):
    ret = func1(n)
    return ret if ret is not None else something_else

撰写回答