【问题标题】:Is it safe to rely on condition evaluation order in if statements?在 if 语句中依赖条件评估顺序是否安全?
【发布时间】:2011-11-21 21:08:45
【问题描述】:

my_var 可以为 None 时使用以下格式是不好的做法吗?

if my_var and 'something' in my_var:
    #do something

问题是如果 my_var 为 None,'something' in my_var 将抛出 TypeError。

或者我应该使用:

if my_var:
    if 'something' in my_var:
        #do something

try:
    if 'something' in my_var:
        #do something
except TypeError:
    pass

换个说法,以上哪个是 Python 中的最佳实践(如果有的话)?

欢迎使用替代品!

【问题讨论】:

    标签: python if-statement


    【解决方案1】:

    取决于条件的顺序 (Python reference here) 是安全的,特别是因为您指出的问题 - 能够短路可能导致一系列条件出现问题的评估非常有用。

    这种代码在大多数语言中都会弹出:

    IF exists(variable) AND variable.doSomething()
        THEN ...
    

    【讨论】:

    • 当我看到类似第二个的代码时,我认为编码人员不了解短路评估的工作原理。
    • -1:文档中没有引用:docs.python.org/library/…
    • @cfi:因为我可以在答案改变后改变我的投票,所以我不清楚问题是什么。
    • @cfi:做任何你认为对他人最有价值的事情。我对评论的 -1 与我的实际投票无关。有趣的是,这允许人们发表与响应的实际价值无关的持久评论。
    • 对于所有消极的人来说,这是一个有效的问题,并且对于每种语言都不相同。除非您使用 andalsoorelse,否则 VB 将同时评估两者
    【解决方案2】:

    是的,它是安全的,它在语言参考中明确且非常明确地定义:

    表达式 x and y 首先计算 x;如果xfalse,则其值为 回来;否则,评估 y 并返回结果值。

    表达式 x or y 首先计算 x;如果x 为真,则其值为 回来;否则,评估 y 并返回结果值。

    【讨论】:

    • 弱:它不是“安全的”——它绝对需要依赖于顺序。
    【解决方案3】:

    我在这里可能有点迂腐,但我想说最好的答案是

    if my_var is not None and 'something' in my_var:
        #do something
    

    区别在于对None 的显式检查,而不是将my_var 隐式转换为TrueFalse

    虽然我确信在您的情况下区别并不重要,但在更一般的情况下,变量很可能不是 None 但仍评估为 False,例如整数值0 或一个空列表。

    因此,与大多数其他发帖人声称它是安全的相反,我会说它是安全的,只要你是明确的。如果您不相信,请考虑这个非常做作的课程:

    class Contrived(object):
        def __contains__(self, s):
            return True
        def __nonzero__(self):
            return False
    
    my_var = Contrived()
    if 'something' in my_var:
        print "Yes the condition is true"
    if my_var and 'something' in my_var:
        print "But this statement won't get reached."
    if my_var is not None and 'something' in my_var:
        print "Whereas this one will."
    

    是的,我知道这不是一个现实的例子,但实际代码中确实会发生变化,尤其是当 None 用于指示默认函数参数时。

    【讨论】:

    • 当然,如果您有一个空列表或任何容器,那么执行in 操作毫无意义。我认为OP完全正确。虽然可以构建任何东西来证明自己的观点,但我不认为任何像样的代码都应该自取其辱。
    • 是的,这是一个人为的例子,但我的主要观点是,当你真正的意思是“if var is not None”时,很容易养成说“if var”的坏习惯。一旦你养成了这种习惯,它就很容易咬你一口,尤其是在使用默认参数时。
    • 我认为很明显 OP 的意图是说 if var 而他就是这样做的。
    【解决方案4】:

    事情没那么简单。作为一个 C# 伙计,我非常习惯于做这样的事情:

    if(x != null && ! string.isnullorempty(x.Name))
    {
       //do something
    }
    

    上面的效果很好,并且按预期进行了评估。然而在 VB.Net 中,以下会产生你意想不到的结果:

    If Not x Is Nothing **And** Not String.IsNullOrEmpty(x.Name) Then
    
       'do something
    
    End If
    

    以上会产生异常。正确的语法应该是

    If Not x Is Nothing **AndAlso** Not String.IsNullOrEmpty(x.Name) Then
    
       'do something
    
    End If
    

    请注意非常细微的区别。这让我困惑了大约 10 分钟(太长了),这也是为什么 C#(和其他)家伙在用其他语言编码时需要非常小心的原因。

    【讨论】:

      【解决方案5】:

      我会使用 try/except,但这取决于您对变量的了解。

      如果您期望变量大部分时间都存在,那么 try/except 操作较少。如果您希望变量在大多数情况下为 None,那么 IF 语句将减少操作。

      【讨论】:

        【解决方案6】:

        它非常安全,我一直都这样做。

        【讨论】:

          猜你喜欢
          • 2013-07-30
          • 1970-01-01
          • 1970-01-01
          • 2019-02-06
          • 2013-04-10
          • 2018-04-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多