在var = func()中,是立即评估func()还是需要var?

时间:2013-09-21 02:55:39

标签: python

我有以下代码

def isIt(arg):
    isA = funcA(arg)
    isB = funcB(arg)

    return (isA and isB)

其中funcB()的计算量比funcA贵,而且超过一半的情况下funcA()为False。

因此,只有当funcA为True

时才进行python调用funcB才有意义
def isIt(arg):
    return (funcA(arg) and funcB(arg))

如果考虑资源消耗,这两个功能是否相同?如果funcB()是生成器上的任何(),该怎么办?

编辑1: 我写第一个代码的意图是,funcA()和funcB()的参数(不是arg)很长,应该会破坏可读性。

PS。我刚刚意识到我可以创建两个本地函数而不是变量来实现与第二个代码相同的效果。

4 个答案:

答案 0 :(得分:2)

  

如果考虑资源消耗,这两个函数是否相同?

它们在功能上并不相同。您似乎已经在问题中理解了这一点,所以我不太确定您的疑虑,但在考虑资源消耗时这一点尤为重要:

def isIt(arg):
    lightweightResult = lightweightFunction(arg)
    expensiveResult = superExpensiveFunction(arg)

    // obviously you can use both results here, so both have been computed.


    // return the values directly, no further computation done here:
    return (lightweightResult and expensiveResult)

您可以这样做的一个原因是,如果您需要expensiveResult其他内容,或者总是需要调用superExpensiveFunction,例如某些资源的初始值设定项。

在第二种情况下,如您所述,funcB(arg)仅在funcA(arg)被评估为真时被评估(返回真值)。这称为short circuiting

def isIt(arg):
    return (lightweightFunction(arg) and superExpensiveFunction(arg))

众所周知,短路是防止不必要执行的好方法。

  

如果funcB()是生成器上的任何(),该怎么办?

除非调用任何一个,否则它永远不会运行生成器。生成器已经是防止不必要执行的好方法,因为它们被懒惰地评估。在这种情况下,我认为短路和发电机组合良好。

正如Blkknght的评论中所指出的,值得注意的是any()all()也有短路,所以在发电机中,发电机只会被评估到确认结果的元素(全部为false或任何为true)。您可以在python.org...#all找到代码。

答案 1 :(得分:1)

我会把它写成

def isIt(arg):
    if not funcA(arg):
        return False
    return funcB(arg)

这有点长,但更符合Python哲学。

编辑:使其成为三行而不是五行。

答案 2 :(得分:0)

它们并不等同。第一个将在每个案例中同时调用funcAfuncB。仅当funcB的结果不真实时,第二个将调用funcA,因为逻辑OR短路。

答案 3 :(得分:0)

是的,你首先调用计算量较小的函数是正确的

以下是我编写函数的方法:

>>> def isIt(arg):
...     if funcA(arg):
...             return funcB(arg)
...     return 0