if <obj>和if <obj>之间的区别不是None

Dyl*_*ger 10 python xml-parsing python-2.7

在编写一些XML解析代码时,我收到了警告:

FutureWarning: The behavior of this method will change in future versions.  Use specific 'len(elem)' or 'elem is not None' test instead.
Run Code Online (Sandbox Code Playgroud)

我曾经在那里if <elem>:检查是否找到了给定元素的值.

有人可以详细说明if <obj>:vs 之间的区别if <obj> is not None:以及Python使用的原因吗?

我几乎总是使用前者因为它更短而不是双重否定,但经常在其他人的源代码中看到后者.

Bre*_*arn 13

if obj is not None测试对象是否不是None. if obj测试是否bool(obj)为True.

有许多对象不是None但是为bool(obj)False:例如,空列表,空字典,空集,空字符串...

使用if obj is not None时要测试对象是否不无.if obj仅在您要测试一般"虚假"时才使用- 其定义与对象有关.

  • 从 lxml etree `find` 返回的对象行为异常。对于从例如 `node = root.find('.//tag/')` 返回的节点,您将获得此 `FutureWarning`。[我写的这篇文章中的更多细节](http://yummycoding.tumblr.com/post/82299053082/lxml-and-futurewarning) 但要点是,如果没有孩子,`node` 将是假的,无论是找到与模式匹配的节点。所以`if node`意味着“匹配节点存在**并且**匹配有子节点”。这就是为什么你被警告要明确:使用`len(node)`来表示“有孩子”;使用 `node is not None` 表示“匹配节点存在”。 (2认同)

Jor*_*ter 8

这个答案专门针对FutureWarning.

首次编写lxml时,lxml.etree._Element如果没有子代,则认为是假的.

结果,这可能发生:

>>> from lxml import etree
>>> 
>>> root = etree.fromstring('<body><h1>Hello</h1></body>')
>>> print root
<Element body at 0x41d7680>
>>> print "root is not Falsey" if root else "root is Falsey"
<string>:1: FutureWarning: The behavior of this method will change in future versions. Use specific 'len(elem)' or 'elem is not None' test instead.
root is not Falsey
>>> # that's odd, a warning
>>> h1 = root.find('.//h1')
>>> print h1
<Element h1 at 0x41d7878>
>>> print "h1 is not Falsey" if h1 else "h1 is Falsey"
h1 is Falsey
>>> # huh, that is weird! In most of python, an object is rarely False
>>> # we did see a warning though, didn't we?
>>> # let's see how the different elements output
>>> print "root is not None" if root is not None else "root is None"
root is not None
>>> print "h1 is not None" if h1 is not None else "h1 is None"
h1 is not None
>>> print "Length of root is ", len(root)
Length of root is  1
>>> print "Length of h1 is ", len(h1)
Length of h1 is  0
>>> # now to look for something that's not there!
>>> h2 = root.find('.//h2')
>>> print h2
None
>>> print "h2 is not Falsey" if h2 else "h2 is Falsey"
h2 is Falsey
>>> print "h2 is not None" if h2 is not None else "h2 is None"
h2 is None
>>> print "Length of h2 is ", len(h2)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: object of type 'NoneType' has no len()
Length of h2 is  >>> 
Run Code Online (Sandbox Code Playgroud)

lxml已经有7年以上的承诺,这种变化将会发生(经过多个版本之后),但从未对威胁进行过贯彻,毫无疑问是因为lxml的核心是多么强大,并且担心会破坏现有的大量代码.

但是,既要明确也要确保你不会犯错,永远不要使用if obj或者if not obj如果该对象具有类型lxml.etree._Element.

而是使用以下检查之一:

obj = root.find('.//tag')

if obj is not None:
    print "Object exists" 

if obj is None:
    print "Object does not exist/was not found"

if len(obj): # warning: if obj is None (no match found) TypeError
    print "Object has children"

if not len(obj): # warning: if obj is None (no match found) TypeError
    print "Object does not have children"
Run Code Online (Sandbox Code Playgroud)