繁体   English   中英

xml.etree.ElementTree的findall()和iterfind()之间有什么区别

[英]What's difference between findall() and iterfind() of xml.etree.ElementTree

我用下面的方式编写程序

from xml.etree.ElementTree import ET

xmlroot = ET.fromstring([my xml content])

for element in xmlroot.iterfind(".//mytag"):
    do some thing

它在我的python(v2.7.1)上工作正常,但是在我将它复制到另一台安装了python v2.6.x的计算机之后,在python文档上不支持iterfind() ,下面的描述已经列出

的findall(匹配)

按标签名称或路径查找所有匹配的子元素。 返回包含文档顺序中所有匹配元素的列表。

iterfind(匹配)

按标签名称或路径查找所有匹配的子元素。 返回一个iterable,以文档顺序生成所有匹配元素。

版本2.7中的新功能。

我的问题是:这两个功能是否相同? 这两个功能有什么区别

如文档中所示 -

  1. findall返回匹配match xpath的完整元素列表,我们可以使用下标来访问它们,例如 -

     >>> root = ET.fromstring("<a><b>c</b></a>") >>> root.findall("./b") [<Element 'b' at 0x02048C90>] >>> lst = root.findall("./b") >>> lst[0] <Element 'b' at 0x02048C90> 

我们也可以使用for循环遍历列表。

  1. iterfind返回一个迭代器(生成器),它不返回列表,在这种情况下我们不能使用下标来访问该元素,我们只能在接受迭代器的地方使用它,例子就是在for循环中。

如果你真的想要遍历返回的列表(这是我的经验中的大部分时间),iterfind会比findall更快,因为findall必须在返回之前创建完整的列表,而iterfind找到(产生)下一个元素只在迭代时匹配match并调用next(iter) (这是在使用for或类似构造迭代列表时内部调用的)。

如果你想要列表,两者似乎都有相似的时间。

两种情况的性能测试 -

In [1]: import xml.etree.ElementTree as ET

In [2]: x = ET.fromstring('<a><b>c</b><b>d</b><b>e</b></a>')

In [3]: def foo(root):
   ...:     d = root.findall('./b')
   ...:     for  y in d:
   ...:         pass
   ...: 

In [4]: def foo1(root):
   ...:     d = root.iterfind('./b')
   ...:     for y in d:
   ...:         pass
   ...: 

In [5]: %timeit foo(x)
100000 loops, best of 3: 9.24 µs per loop

In [6]: %timeit foo1(x)
100000 loops, best of 3: 6.65 µs per loop

In [7]: def foo2(root):
   ...:     return root.findall('./b')
   ...: 

In [8]: def foo3(root):
   ...:     return list(root.iterfind('./b'))
   ...: 

In [9]: %timeit foo2(x)
100000 loops, best of 3: 8.54 µs per loop

In [10]: %timeit foo3(x)
100000 loops, best of 3: 8.4 µs per loop

如果你这样做

for element in xmlroot.iterfind(".//mytag"):
    do some thing

然后一次一个地从XML文件中检索元素(每个循环一个元素)。

如果你这样做

for element in xmlroot.findall(".//mytag"):
    do some thing

将立即检索所有元素并将其存储到(临时)列表中。 只有这样, for循环才会开始迭代该列表。

这意味着第二种方法在开始时需要更长的时间(因为它必须构建该列表)并使用更多内存(同样的原因)。 此外,如果您需要在到达最后一个元素之前退出for循环,那么您将完成不必要的工作。 另一方面,一旦你进入for循环,第二种方法可能会更快一些。 通常,第一种方法(“懒惰评估”)的好处超过了这个缺点。

在您的情况下,切换到findall可能是安全的。

正如你的链接所说,iterfind返回一个生成器(yield)并且findall返回一个列表。

唯一的区别是,你可以在这里查看例如,看看这两种类型之间的区别。

在这种情况下,它主要是内存性能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM