什么是最符合Python风格的有条件返回函数的方式?

4

假设有两个函数,我希望func2返回func1的结果,但是如果func1的结果为None,则返回其他结果。有两种方法可以实现这个功能,但它们都有些不太对。

第一种方法:

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,也不需要创建新变量?如果这确实是唯一的方法,你会推荐哪种方式?我目前使用第二种方式(将 foo 设置为 func1 返回的内容,然后返回 foo,除非 foo == None)

另外,请记住,在我的实际代码中,我调用多个不同的函数,并且我想返回第一个不是 None 的函数,这只是一个更简单的代码版本,以达到问题的效果。


1
文档中建议对于像 None 这样的单例,应该使用 isis not 而不是 ==!=。请参考此处:https://dev59.com/6HE95IYBdhLWcg3wrPwn - TheSoundDefense
请不要使用 == Trueif condition: 就足够了,而且更不容易出错(因为比较链,如果添加其他比较,你很可能会产生错误的表达式)。 - Martijn Pieters
另外,如果你要检查一个类型,请使用 isinstance - blakev
好的,请记住这不是我的代码,而是我为了展示我所尝试做的事情而编写的简化代码。 - DJMcMayhem
4个回答

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)

1
如果你需要从 func1(n) 返回一个假值,那么请使用 ret = func1(n); return ret if ret is not None else something_else - dano
嗯,也许我在问题中应该明确说明,但我有许多不同的函数,并且我想返回第一个不是None的函数。我猜我可以这样做 return func1(n) or func2(n) or func3(n) or something_else - DJMcMayhem

6

给调用func1的结果取个名字是比较便宜的,所以我会这样写函数:

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

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”返回falsey值,此方法也有效。
或者,考虑到“func1”的内容,您可以这样做:
def func1(n):
    return foo

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

这取决于 func1 的实际内容。


我知道else是不必要的。此外,您的修改基本上就是我的代码现在的样子,我只想知道是否绝对需要创建一个名为foo的变量。而且,func1的内容过于复杂,无法将“条件”添加到func2中,特别是考虑到func1的条件调用其他函数,并返回第一个不返回None的那些函数。 - DJMcMayhem
1
如果iCodez的回答限制成为问题,我想不到任何避免创建变量foo的方法。 - neil

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接