在if语句中依赖条件评估顺序安全吗?
当my_var
可以是无时使用以下格式是不好的做法吗?在if语句中依赖条件评估顺序安全吗?
if my_var and 'something' in my_var:
#do something
的问题是,'something' in my_var
将抛出一个TypeError如果my_var是无。
或者我应该使用:
if my_var:
if 'something' in my_var:
#do something
或
try:
if 'something' in my_var:
#do something
except TypeError:
pass
重新表述的问题,它的上面是Python中的最佳实践(如果有的话)?
替代品是欢迎的!
根据条件的顺序(Python reference here)安全可靠,特别是因为您指出的问题 - 能够短路评估可能会导致一系列条件中的问题,这是非常有用的。
这种代码在大多数语言弹出:
IF exists(variable) AND variable.doSomething()
THEN ...
这是完全安全的,我做这一切的时候。
我会去尝试/除了,但它取决于你所了解的变量。
如果您希望变量会在大多数情况下存在,那么尝试/除了少一些操作。如果你期望变量在大多数情况下都是None,那么IF语句将会减少操作。
是的,它是安全的,它是明确和很清楚的语言参考定义:
表达
x and y
首先评估x
;如果x
是false
,则返回其值 ;否则,y
评估为 并返回结果值。表达式
x or y
首先评估x
;如果x
为真,则返回值为 ;否则,y
评估为 并返回结果值。
并非如此简单。作为一个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#(和其他人)在使用其他语言进行编码时需要非常小心的原因。
我可能是有点迂腐在这里,但我要说的是最好的答案是
if my_var is not None and 'something' in my_var:
#do something
的区别在于为None
明确的检查,而不是my_var
到True
或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
用于表示默认的函数参数。
当我看到第二个代码时,我假设编码器不理解短路评估的工作原理。 – Dana 2009-04-15 16:04:14
-1:文档中没有引用:http://docs.python.org/library/stdtypes.html#boolean-operations-and-or-not – 2009-04-15 17:02:31
@cfi:因为我可以在答案更改后更改我的投票,我不清楚问题在哪。 – 2011-11-22 19:12:16