【问题标题】:recursion None python递归 无 python
【发布时间】:2014-08-05 12:37:59
【问题描述】:

这是一个 XML 解析器代码 sn-p,它返回 None 值。这是一个大型 XML 文件,其中包含很多这样的子字段:

<root>
    <field name ="1">
        <field name ="2" showname ="ZZZ">
            <field name ="3" showname="YYY">
                <field name ="4" showname="XXX"/>
            </field>
        </field>
    </field>

findall() 查找所有带有标签的元素,它们是当前元素的直接子元素。我试过这个,但它没有返回。它也不打印任何内容。

def findXXX(field):
    if field.get('name') == 'XXX' :
        return field.get('showname')
    else:
        for fieldchild in field.findall('field'):
            return findXXX(fieldchild)

如果我这样写,它会打印正确的值,但是它返回 None。

def findXXX(field):
    if field.get('name') == 'XXX' :
        print field.get('showname')
        return field.get('showname')
    else:
        for fieldchild in field.findall('field'):
            findXXX(fieldchild)

【问题讨论】:

  • 在您的第一个代码块中,我怀疑在for 循环内有一个无条件的return 是一个逻辑错误;它只会在终止前迭代一次。
  • 你的递归只探索树的最左边的分支,因为你 return 立即在你的 for 循环中。要么在列表中累积并在循环结束时返回,要么将其重写为生成器。
  • 顺便说一句,您是要测试'name' 属性还是'showname' 属性?您正在针对 'XXX' 进行测试。

标签: python recursion elementtree


【解决方案1】:

在您的第二个版本中,您忽略递归调用的返回值。您的第一个版本至少仍然返回该返回值:

for fieldchild in field.findall('field'):
    return findXXX(fieldchild)

您函数中的return 语句返回到直接调用者,而不是返回到findXXX() 的最外层第一次调用的调用者。

但是现在只有field.findall() 列表中的first field 的结果会返回一些东西。您可能希望返回第一个 不是 None

for fieldchild in field.findall('field'):
    result = findXXX(fieldchild)
    if result is not None:
        return result

这将对每个 field 元素进行递归搜索,并返回 first 不是 None 的此类递归调用的结果。

请注意,您没有 递归;您还可以使用XPath expression 来搜索树,而不必自己递归:

field.find(".//field[@showname='XXX']")

这会返回第一个name 属性设置为XXXfield 标记,递归搜索

演示:

>>> from xml.etree import ElementTree as ET
>>> tree = ET.fromstring('''\
... <root>
...     <field name ="1">
...         <field name ="2" showname ="ZZZ">
...             <field name ="3" showname="YYY">
...                 <field name ="4" showname="XXX"/>
...             </field>
...         </field>
...     </field>
... </root>
... ''')
>>> tree.find(".//field[@showname='XXX']")
<Element 'field' at 0x108519bd0>
>>> tree.find(".//field[@showname='XXX']").get('name')
'4'

【讨论】:

  • @user3816048:不,我的回答与你写的不完全一样。
【解决方案2】:

我建议您使用 BeautifulSoup。它易于学习,具有良好的文档。 http://www.crummy.com/software/BeautifulSoup/bs4/doc/

可以使用下面的代码实例化一个汤对象,其中“标记”是一个包含您的 XML 的字符串,或 XML 文件的输入文件句柄:

BeautifulSoup(markup, "xml")

【讨论】:

  • 这里的问题是如何处理递归。就目前而言,这更像是一种评论。
  • 我的观点是,当一个经过良好测试的模块已经完成 XML 解析代码时,为什么要编写它。
  • ElementTree 和 BeautifulSoup 是为用户提供树模型的两种不同方法。
  • 但请注意,BeautifulSoup 确实更适合 HTML。 XML 支持很不错,但是对于 XML 标准的更多深奥元素(例如处理指令)仍有一些错误和参差不齐的覆盖。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-19
  • 2013-02-26
  • 2014-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多