在if语句中依赖条件评估顺序是否安全?

时间:2009-04-15 15:57:19

标签: python if-statement

my_var可以是无?

时,使用以下格式是不好的做法
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中的最佳实践(如果有的话)?

欢迎替代方案!

6 个答案:

答案 0 :(得分:81)

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

这种代码以大多数语言弹出:

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

答案 1 :(得分:31)

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

  

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

     

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

答案 2 :(得分:2)

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

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

区别在于None的显式检查,而不是my_varTrueFalse的隐式转换。

虽然我确信在您的情况下区别并不重要,但在更一般的情况下,变量很可能不是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用于表示默认函数参数时。

答案 3 :(得分:1)

这是非常安全的,我一直这样做。

答案 4 :(得分:1)

我会选择try / except,但这取决于你对变量的了解。

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

答案 5 :(得分:1)

这不是那么简单。作为C#dude,我非常习惯于这样做:

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#(和其他)家伙在用其他语言编写代码时需要非常小心。