83

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

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

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

或者我应该使用:

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

或者

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

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

欢迎替代品!

4

6 回答 6

99

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

大多数语言都会出现这种代码:

IF exists(variable) AND variable.doSomething()
    THEN ...
于 2009-04-15T15:59:25.493 回答
39

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

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

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

于 2009-04-15T16:08:21.837 回答
4

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

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

区别在于显式检查None,而不是隐式转换my_varTrueor False

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

于 2009-09-01T11:37:32.227 回答
2

没那么简单。作为一个 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#(和其他)花花公子在用其他语言编码时需要非常小心的原因。

于 2009-06-05T13:31:51.000 回答
1

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

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

于 2009-04-15T16:00:04.103 回答
0

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

于 2009-04-15T15:59:43.543 回答