【问题标题】:Python - recursion not workingPython - 递归不起作用
【发布时间】:2017-01-13 21:02:35
【问题描述】:

我有以下代码:

d = {'init':
       [{'solve':
                 [{'subsolve':
                       [{'vals': [{'Blade summary': 'asdf'},
                                  {'Blade summary': 'fdsa'}]}]},
                  {'subsolve':
                       [{'vals': [{'Blade summary': 'ffff'}]}]}]},
        {'solve':
                 [{'subsolve':
                       [{'vals': 'bbbb'}]}]}]}

def parseDics(lst, mainReg):
    print('call')
    for dic in lst:
        for key, vals in dic.items():
            if key == mainReg:
                if mainReg == 'vals':
                    yield vals
                parseDics(vals, 'vals')
            else:
                parseDics(vals, mainReg)



if __name__=='__main__':
    pp.pprint(list(parseDics(d['init'], 'solve')))

功能本身并不完整,但目前这不是问题。问题似乎在于递归调用不起作用。

如果我现在尝试运行它,我只会得到以下输出:

call
[]

所以这个函数只被调用了一次。当我尝试进入嵌套函数调用(我正在使用 PyCharm)时,我根本无法进入,并且函数调用“过度”。

我做错了什么?为什么我的函数没有被递归调用?

【问题讨论】:

  • yield from parseDics(vals, 'vals')?
  • 您的代码只检查键是solve 还是vals,它永远不会递归到以subsolve 为键的字典项中。

标签: python python-3.x dictionary recursion pycharm


【解决方案1】:

parseDics 不是一个常规函数,它是一个生成器。所以你需要像一个生成器一样调用它,而不是一个普通的函数,否则它不会工作。第一个调用有效,因为当您调用list(parseDicts(...)) 时,列表构造函数调用parseDicts 作为生成器。但是在parseDicts中,你尝试递归调用parseDicts作为一个函数,这是行不通的。

如果您使用的是 Python 3.3+,请将递归调用更改为使用 yield from

def parseDics(lst, mainReg):
    print('call')
    for dic in lst:
        for key, vals in dic.items():
            if key == mainReg:
                if mainReg == 'vals':
                    yield vals
                yield from parseDics(vals, 'vals')
            else:
                yield from parseDics(vals, mainReg)

对于旧版本的 Python,您需要遍历这些递归调用并生成生成的每个值:

def parseDics(lst, mainReg):
    print('call')
    for dic in lst:
        for key, vals in dic.items():
            if key == mainReg:
                if mainReg == 'vals':
                    yield vals
                for val in parseDics(vals, 'vals'):
                    yield val
            else:
                for val in parseDics(vals, mainReg):
                    yield val

将生成器作为函数调用只会创建生成器,它不会运行它。例如:

>>> def my_gen():
    print("my_gen()")
    for i in range(5):
        print(i)
        yield i

>>> my_gen()
<generator object my_gen at 0x00000000045B6B48>

>>> list(my_gen())
my_gen()
0
1
2
3
4
[0, 1, 2, 3, 4]

【讨论】:

    【解决方案2】:

    您需要对递归调用的结果进行实际操作。由于您使用带有值的yield,因此您可能也需要在那里使用它。

    【讨论】:

      【解决方案3】:

      在 Python 3.4 中,对于 Python 2,您可以使用 yield from parseDics(vals, 'vals')

      for val in parseDics(vals, 'vals'):
          yield val
      

      【讨论】:

        猜你喜欢
        • 2015-09-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-14
        • 2019-01-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多