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

my_var可以是None时,使用下面的格式不好吗?

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

问题是,如果my_var是None 'something' in my_var中的'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引用 )是安全的,特别是因为你指出的问题 – 能够短路评估可能会导致一系列条件中的问题是非常有用的。

这种代码在大多数语言中popup:

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

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

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

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

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

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

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

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

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

我会去尝试/除了,但这取决于你知道什么variables。

如果你期望variables会在大部分时间存在,那么try / except就是less一些操作。 如果你期望variables在大多数情况下都是None,那么一个IF语句就会less一些操作。

这并不简单。 作为一个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#(和其他人)在使用其他语言进行编码时需要非常小心的原因。