【问题标题】:Need lazy evaluation for a function returning large data需要对返回大数据的函数进行延迟评估
【发布时间】:2014-02-27 21:09:55
【问题描述】:

现在真的很想念 Haskell。

我有这个代码:

for i in someFunc(arg0...argN):
    //some logic

问题是someFunc 的返回值很大,我的内存快用完了。

我以为我可以将它封装在生成器中,但这无济于事,因为我无法控制 someFunc,又名:

def gen_someFunc(someFunc):
    for i in someFunc(arg0...argN):
        yield i

没有帮助,因为someFunc 仍会立即进行评估。如何懒惰地评估someFunc

【问题讨论】:

  • 澄清一下,问题是someFunc返回的物化数据集太大了?
  • 这个问题没有通用的解决方法。您需要更改 someFunc、替换它或以其他方式调用它。
  • @Edgar:Haskell 也救不了你。如果一个函数决定返回ByteString 而不是Lazy.ByteString,你同样会迷路。您无法更改现有代码的行为。懒惰有时会付出巨大的代价。
  • @EdgarAroutiounian:Niklas 的意思是这里的“错误”不在于 Python(或任何任意的非 Haskell 语言);这取决于编写非惰性函数的人。
  • @Edgar:Haskell 中的列表相当于 Python 中的生成器。因此,假设该函数将返回一个“大量”生成器,那么您在 Python 中也不会遇到问题。没有人会从 Haskell 函数中返回未经评估的“大量列表”,这是导致堆栈溢出的一种非常确定的方式(由于堆栈上积聚了未经评估的 thunk)

标签: python lazy-evaluation


【解决方案1】:

在 Python(或 Haskell,这不是)中,您不能懒惰地将返回完全物化对象的函数排队。使用该功能后可能会发生懒惰,但是如果一次将数据全部转储给您,您将无能为力。

也许有一些参数用于调用你还不知道的函数,这会让你懒惰地评估它,但我们从这里给出的信息中不知道这一点。

如果您可以在内存中保留对数据的初始调用,那么作为生成器调用它的 Pythonic 方式将是

gen_some_func = iter(someFunc(arg0...argN))

不要写这个函数,以后再调用。

def gen_someFunc(someFunc):
    for i in someFunc(arg0...argN):
        yield i

【讨论】:

    猜你喜欢
    • 2012-05-12
    • 2015-11-12
    • 1970-01-01
    • 2015-06-01
    • 2016-08-14
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多