【问题标题】:Why is my function only returning the object in the second return statement not the first return statement which is actually triggering the return为什么我的函数只返回第二个返回语句中的对象而不是第一个实际触发返回的返回语句
【发布时间】:2021-03-17 18:27:37
【问题描述】:

我有一些 xml,其中包含一些未知深度的元素,这里是一个示例元素

<someElement anAttribute="descriptiveandimportant">
<firstChild>
<childOfFirstChild anAttribute="someText">text_value</childOfFirstChild>
</firstChild>
<secondChild>
<daughterOfSecondChild>anotherText_value_1</daughterOfSecondChild>
<sonOfSecondChild>anotherText_value_2</sonOfSecondChild>
</secondChild>
</someElement>

我不知道 someElement 有多少个孩子,也不知道每个孩子有多少个孩子。 . .它真的没有那么深,但我正在处理一些野外数据,我不能假设我提前知道所有的孩子和他们的孩子。

我想要每个独特的子元素及其子元素。 . .

    myOutput = [firstChild, childOfFirstChild, second_child, daughterOfSecondChild, sonOfSecondChild]

我写了一个函数——打印语句可以帮助我解决问题

def get_children(some_element_list):

    new_elements_list = []

    for e in some_element_list:
        new_elements_list.append(e)
        for child in e.iterchildren():
            if child == e:
                continue
            if child in some_element_list:
                continue
            new_elements_list.append(child)
    print (new_elements_list)

    if new_elements_list == some_element_list:
        print ('passed the test')

        return some_element_list[1:]   # when triggered

    print('going to loop again')
    some_element_list = get_children(new_elements_list) # returns here


    return some_element_list  # if this is not present nothing is returned

这是使用 someElement 运行函数后的结果

>>> y = get_children([someElement])
[<Element someElement at 0x23f4cbbff40>, <Element firstChild at 0x23f4cc76f90>, <Element secondChild at 0x23f4cbbfc70>]
going to loop again
[<Element someElement at 0x23f4cbbff40>, <Element firstChild at 0x23f4cc76f90>, <Element childOfFirstChild at 0x23f4cc76a90>, <Element secondChild at 0x23f4cbbfc70>, <Element daughterOfSecondChild at 0x23f4cc769a0>, <Element sonOfSecondChild at 0x23f4cc76b30>]
going to loop again
[<Element someElement at 0x23f4cbbff40>, <Element firstChild at 0x23f4cc76f90>, <Element childOfFirstChild at 0x23f4cc76a90>, <Element secondChild at 0x23f4cbbfc70>, <Element daughterOfSecondChild at 0x23f4cc769a0>, <Element sonOfSecondChild at 0x23f4cc76b30>]
passed the test

我很挣扎,因为我最初有 final return 语句而没有指定要返回的任何内容 - 一旦我在第二个 return 语句中命名 some_element_list 函数返回 some_element_list[1:] - 换句话说它返回第一个 return 语句中定义的内容。

我从不编写 some_element_list = some_element_list[1:]。

最后,当我试图思考如何提出这个问题时,我将最终的 return 语句更改为

return 'is this not interesting'

这就是返回的 - 不是 some_element_list[1:]

总之,我看到了两件对我来说没有意义的事情

  1. 我必须在函数的最终返回语句中指定一些对象才能返回任何内容 - 即使在函数结束之前触发了返回。
  2. some_element_list 实际上是 some_element_list[1:] 如果在第一个 return 语句中是这样定义的

基于下面的答案并且与问题有一定距离我现在理解了问题代码中的 cmets 我希望有助于向下一个出现的人解释我的错误是认为当第一次返回被触发时它返回 调用者的strong>外部下面的解释帮助我到达那里

【问题讨论】:

    标签: python-3.x xml recursion lxml


    【解决方案1】:

    这是基本的递归,但令人困惑,因为它添加了与问题无关的xml 位。

    我能想到的最好的解释方式是:

        if new_elements_list == some_element_list:
            return some_element_list[1:]
    

    是你的基本情况。

    它会在未指定的深度停止递归。 但是,您的结果仍然需要从嵌套调用中“冒泡”。 由于这个例子只重复了两次,所以很容易给你一个例子来说明这是如何发生的。

    假设some_element_list = get_children(new_elements_list) 不是递归的,它只是调用另一个函数。 这就是您的案例的外观。

    import lxml.etree
    
    def get_children(some_element_list):
        new_elements_list = []
        for e in some_element_list:
            new_elements_list.append(e)
            for child in e.iterchildren():
                if child == e:
                    continue
                if child in some_element_list:
                    continue
                new_elements_list.append(child)
        # This can removed since it's actually only ever True in the 
        # recursive call
        # if new_elements_list == some_element_list:
        #     return some_element_list[1:]
        some_element_list = get_children_inner_call(new_elements_list)
        return some_element_list
    
    def get_children_inner_call(some_element_list):
        new_elements_list = []
        for e in some_element_list:
            new_elements_list.append(e)
            for child in e.iterchildren():
                if child == e:
                    continue
                if child in some_element_list:
                    continue
                new_elements_list.append(child)
        # Since it will be true in this "recursive" call
        # it can be removed here
        # if new_elements_list == some_element_list:
        return some_element_list[1:]
    
    foo = lxml.etree.fromstring(
    '''<someElement anAttribute="descriptiveandimportant"> 
    <firstChild>
    <childOfFirstChild anAttribute="someText">text_value</childOfFirstChild>
    </firstChild>
    <secondChild>
    <daughterOfSecondChild>anotherText_value_1</daughterOfSecondChild>
    <sonOfSecondChild>anotherText_value_2</sonOfSecondChild>
    </secondChild>
    </someElement>
    ''')
    
    print(get_children(foo))
    

    如您所见,some_element_list 是从内部调用获得的,实际上是some_element_list[1:]。然后将其返回给您的外部函数调用。

    如果您之前使用过递归,那么您之前已经看到过这种模式。但是您的示例中有很多噪音,可能会导致混乱。

    【讨论】:

    • 感谢您非常清楚的解释。您的解释与正在发生的事情完全吻合,我需要对此进行更多思考,但您给了我工具
    • 有点距离,现在我明白了 - 当第一次返回被触发时,它返回到函数内部而不是函数外部的调用者 - 傻我
    猜你喜欢
    • 2015-08-14
    • 1970-01-01
    • 2013-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-02
    • 1970-01-01
    相关资源
    最近更新 更多