【问题标题】:Python: How to condition the execution of a part of a function on the return valuesPython:如何以返回值为条件执行部分函数
【发布时间】:2014-09-15 23:51:24
【问题描述】:

我想实现一个函数f,它返回两个值xy给定输入w。该函数首先使用w 计算x 的值,然后使用x 的计算值计算y。但是,由于y 的计算成本很高,因此我希望该函数仅在需要该函数的结果时才计算其值。

也就是说,下面对f 的调用将不会执行计算y 的部分函数...

x, _ = f(w)

...下面的调用将执行它...

x, y = f(w)

可以这样定义函数吗?当然,一个直接的替代方法是将一个额外的布尔变量传递给f,它确定是否要计算y,但我想知道是否还有其他方法可以做到这一点。谢谢!

【问题讨论】:

  • 正如 Marijn 所说,这是不可能的。此外, _ 实际上是一个变量:尝试在该语句之后执行 print _

标签: python function


【解决方案1】:

这是生成器的完美案例,您可以使用它延迟执行,直到您想要它为止。

def defer_huge_operation(w):
    ...
    yield x
    ...
    ...
    ...
    yield y

op = defer_huge_operation(w)
x = next(op)
...
...
y = next(op)

当你执行next(op)时,它会产生x的值,并且控制权将返回到主程序,当你再次执行next(op)时,将从你离开的地方继续执行,并且将执行巨大的操作给你y

注意:一旦你完全消耗了生成器,进一步的next 调用生成器将引发StopIteration 异常。即使你想再次做同样的操作,你也需要像这样创建一个新的生成器对象

op = defer_huge_operation(w)

如果要获取生成器产生的所有值,只需使用listtuple 函数对其进行迭代,就像这样

returned_values_list = list(defer_huge_operation(w))

【讨论】:

  • 我通常认为生成器用于生成相同类型的数据序列,而不是相关计算的两个部分。这要求调用者知道期望有多少值。虽然它有效,但我不确定我是否会认为它是惯用的。
  • 我认为 egenerator 的想法很不错,但为什么不只做 2 个函数 - 你有继续所需的值,所以可以有条件地调用繁重的函数。
  • 谢谢,这很有帮助!我以前不知道收益率。所以我假设只要我只需要x,我就可以反复做一个op = defer_huge_operation(w),然后只做一个x = next(op),然后最后在x = next(op)之后添加一个y = next(op)我确实需要y
  • @user1953384 是的,应该没问题 :)
  • @user1953384 虽然它可以工作,但我会说这是不好的做法:它不可读且容易出错(如果您稍后将第一个 next(op) 注释掉怎么办?)。我建议您使用两个不同的函数,一个用于x,另一个用于y,或者传递一个布尔标志,或者使用我建议的惰性道具结果。这些在实践中要好得多。
【解决方案2】:

另一种选择是从函数返回一个带有lazy properties 的对象,因此只有在您第一次读取结果时才会评估结果。

即。

result = f(w)
x = result.x  # only x is calculated now
y = result.y  # y is calculated only here
y2 = result.y  # y isn't calculated a second time

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    • 2016-06-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    相关资源
    最近更新 更多