【问题标题】:lazy evaluation in Python3Python3 中的惰性求值
【发布时间】:2020-05-19 09:56:28
【问题描述】:

假设我有一个带有副作用的函数(在示例中,副作用是打印了一些东西)。是否有任何版本的 any() 或列表可迭代的任何构造在找到 True 结果后不会触发副作用?

例如,假设这个函数:

def a(x):
   print("A function got: " + str(x))
   return x == 2

人们可能希望这个调用可以解决问题。当然不是:

any([
  a(i) for i in range(5)
])

哪些打印:

A function got: 0
A function got: 1
A function got: 2
A function got: 3
A function got: 4

但我希望它打印出来:

A function got: 0
A function got: 1
A function got: 2

为什么? Range 是一个可迭代的,列表推导正在产生一个可迭代的,我有点期望 Python 将它们链接在一起并在 any() 函数停止消耗后立即停止执行整个事情,一旦它达到第一个 True 就应该这样做.

我误会了什么?如果有的话,哪个版本的 this 会以这种方式运行?

【问题讨论】:

  • 嗯...不要使用列表推导式?
  • 呼叫any(a(i) for i in range(5)),没有[]。使用括号,您正在创建一个列表推导,因此首先它创建一个包含生成器生成的所有元素的列表,然后将其传递给any。如果没有括号,any 只会根据需要在生成器中迭代尽可能多的元素。
  • 哇。这建筑太棒了!我不知道。我现在要到处使用它。几个方括号有什么不同。大吃一惊。您可以将其粘贴为@jdehesa 的答案吗?
  • @BillHuneke 没关系,把已经发帖的那张当作已接受,不用重复答案。

标签: python lazy-evaluation


【解决方案1】:

每当您使用列表时,都会评估所有值。获得惰性评估的唯一方法是将其保留为迭代器。您可以使用生成器理解来做到这一点:

any(a(i) for i in range(5))

需要明确的是,使用方括号与使用any(list(a(i) for i in range(5))) 相同。

【讨论】:

  • 不完全正确,any(map(a, range(5)) 在没有生成器的情况下是懒惰的。
  • this: 返回一个迭代器,将函数应用于可迭代的每个项目,并产生结果
  • 产生结果
  • map 是一个生成器(俗称生成值),但它不是generator(它是由生成器表达式和生成器函数创建的 Python 类型)。跨度>
  • @HeapOverflow: any(map(a, range(5)) 确实很懒。在你写下缺失的)之前,它不会被解释。
【解决方案2】:

另一个有效的解决方案如下,首先从 itertool 导入,然后,

l=list(takewhile(lambda x:a(x) is False, range(5)))

【讨论】:

    【解决方案3】:

    您也可以简单地运行循环并从中退出break

    for i in range(5):
        if a(i):
            break
    

    所以

    def my_any(func, it):
        for i in it:
            if func(i):
                break
    
    my_any(a, range(5))
    

    【讨论】:

      【解决方案4】:

      您可以通过在列表理解中添加条件来使用以下代码

      def a(x):
         print("A function got: " + str(x))
      
      any([
        a(i) for i in range(5) if i<3 
      ])
      

      【讨论】:

      • 这假设您知道返回条件并可以直接将其应用于数据。在这个极其简单的示例中,这可能会起作用,但 a(x) 可能是一个很大的计算,你不能期望提前知道(这就是为什么你首先将它作为一个函数)。这个答案完全没有抓住问题的重点......
      • 另外,问题不在于 HOW 来实现所需的输出,而更多的是 WHY 我们得到实际的输出
      猜你喜欢
      • 1970-01-01
      • 2011-02-23
      • 2013-12-30
      • 2016-10-11
      • 2010-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多