【问题标题】:Does Python evaluate if's conditions lazily? [duplicate]Python 会懒惰地评估 if 的条件吗? [复制]
【发布时间】:2012-12-07 07:02:39
【问题描述】:

例如,如果我有以下语句:

if( foo1 or foo2)
    ...
    ...

如果 foo1 为真,python 会检查 foo2 的条件吗?

【问题讨论】:

标签: python lazy-evaluation


【解决方案1】:

一个简短的演示是比较两者之间的时间差

all(xrange(1,1000000000))

any(xrange(1,1000000000))

all() 必须检查每一个值,而 any() 可以在找到第一个 True 后放弃。因此,作为生成器的 xrange 也会在评估器完成后立即放弃生成事物。出于这个原因,all 将消耗大量 RAM 并需要很长时间,而 any 将只使用几个字节并立即返回。

【讨论】:

    【解决方案2】:

    and or 很懒

    & | 不偷懒

    【讨论】:

      【解决方案3】:

      Python 的惰性可以通过以下代码证明:

      def foo():
          print('foo')
          return False
      
      def bar():
          print('bar')
          return False
      
      foo() and bar()         #Only 'foo' is printed
      

      另一方面,

      foo() or bar()
      

      会导致 'foo' 和 'bar' 都被打印出来。

      【讨论】:

        【解决方案4】:

        确实是or部分短路了:

        >>> 1 or 1/0  #also 0 and 1/0
        1
        >>> 0 or 1/0  #also 1 and 1/0
        
        Traceback (most recent call last):
          File "<pyshell#1240>", line 1, in <module>
            0 or 1/0
        ZeroDivisionError: integer division or modulo by zero
        

        【讨论】:

          【解决方案5】:

          这在技术上不是惰性求值,而是短路布尔表达式。

          懒惰的评估有一些不同的内涵。例如,真正的惰性评估可能会允许这样做

          def foo(arg) :
              print "Couldn't care less"
          
          foo([][0])
          

          但 Python 没有。

          Python 也很好,因为它“回声”它是布尔参数。例如,一个 or 条件返回它的第一个“真”参数或最后一个参数(如果所有参数都是“假的”)。与条件相反。

          所以“回声参数”布尔意味着

          2 和 [] 和 1

          计算为 [],并且

          [] 或 1 或 2

          计算为 1

          【讨论】:

          • 惰性求值是一个包罗万象的术语,也可以指逻辑运算符的短路行为。如果您的意思是按需调用,则通常称为“按需调用”,因为惰性评估可能意味着很多。
          • 我不同意。当他们的意思是“短路评估”时说“懒惰的评估”的人是错误的。 “按需调用”是“懒惰评估”的同义词。我同意它不太容易被滥用。
          • @PeteIsNeat 如果您想成为技术规范主义者,“惰性评估”是实现按需调用语义的众多方法之一。它们不是同义词,也不是等价的。我是一个描述主义者,所以当人们谈论“懒惰的行为”并且从上下文中很明显他们在谈论短路时,我并不介意。 :)
          • 我是在谈话中引入“懒惰评估”的人。我只是想添加一些附加的上下文。如果您的意思是“短路评估”,那么说“惰性评估”是一种误导,我想确保每个人都理解这一点。至于“惰性评估”是否与“按需调用”同义……维基百科page对我来说是正确的。
          • Wikipedia contradicts itself in this case:“延迟评估是按需调用语义最常用的实现策略,但也存在变体——例如乐观评估。” OP sorta-kinda 通过询问如何“懒惰地评估事物”在对话中引入了懒惰的评估。
          【解决方案6】:

          是的,Python 会延迟计算,因此不会检查 foo2

          如果我不知道密钥是否存在,我一直使用它来从类似字典的对象中获取项目:

          if 'key' in mydict and mydict['key'] == 'heyyo!':
              do_stuff()
          

          查看@unutbu 的回答以获得更完整的解释。

          【讨论】:

          • 对于那个用例,我认为if mydict.get("key") == 'heyyo!': 也可以工作——如果找不到密钥,.get 将返回None(或指定的默认值)。
          • 正确,它会的,所以我一般不会将它用于实际的字典,而是用于没有.get 方法的类字典对象(通常来自外部模块)。跨度>
          • @DSM 实际上,对于您的用例,我会简单地使用if mydict.get("key"):,因为None 将评估为False
          • ?但是你会失去 'heyyo!' 比较。
          【解决方案7】:

          是的,Python 懒惰地评估布尔条件。

          docs say

          表达式 x 和 y 首先计算 x;如果 x 为假,则其值为 回来;否则,对 y 求值,结果值为 返回。

          表达式 x 或 y 首先计算 x;如果 x 为真,则其值为 回来;否则,对 y 求值,结果值为 返回。

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-04-01
          • 2019-05-13
          • 2017-04-30
          • 1970-01-01
          • 2019-01-07
          • 2017-01-13
          • 1970-01-01
          相关资源
          最近更新 更多