0

我有以下代码

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() 是生成器上的 any() 怎么办?

编辑 1:我打算像第一个代码一样编写是,funcA() 和 funcB() 的参数(不是 arg )很长,足以破坏可读性。

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

4

4 回答 4

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总是需要调用 if,例如某些资源的初始化程序。

正如您所描述的,在第二种情况下,funcB(arg)仅在funcA(arg)评估为 true 时才评估(返回真实值)。这称为短路

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

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

如果 funcB() 是生成器上的 any() 怎么办?

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

正如Blkknght的评论中所指出的,值得注意的是,any()并且all()也有短路,因此在生成器中,生成器只会被评估到确认结果的元素(全部为假或任何为真)。您可以在python.org...#all上查看代码。

于 2013-09-21T03:18:48.007 回答
1

我会把它写成

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

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

编辑:将其改为三行而不是五行。

于 2013-09-21T03:01:40.937 回答
0

它们不是等价的。第一个将在每种情况下funcA都调用。只有当结果不真实时,funcB第二个才会调用,因为逻辑或短路。funcBfuncA

于 2013-09-21T02:58:45.550 回答
0

是的,您首先调用计算成本较低的函数是正确的

这是我编写函数的方式:

>>> def isIt(arg):
...     if funcA(arg):
...             return funcB(arg)
...     return 0
于 2013-09-21T03:14:19.747 回答