在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
; 如果x
为false
,则返回其值; 否则,评估y
并返回结果值。expression式
x or y
首先评估x
; 如果x
为真,则返回其值; 否则,评估y
并返回结果值。
我可能在这里有点迂腐,但我会说最好的答案是
if my_var is not None and 'something' in my_var: #do something
区别在于显式检查None
,而不是将my_var
隐式转换为True
或False
。
虽然我相信在你的情况下,区别并不重要,在更一般的情况下,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#(和其他人)在使用其他语言进行编码时需要非常小心的原因。