需要帮助了解这个递归函数是如何工作的

时间:2009-12-07 13:40:48

标签: python recursion

这是一个功能(归功于用户Abbot,用于在另一个问题中提供)

def traverse(ftp):

    level = {}
    for entry in (path for path in ftp.nlst() if path not in ('.', '..')):
        ftp.cwd(entry)
        level[entry] = traverse(ftp) 
        ftp.cwd('..')
    return level

这是我不明白的:当python进入函数时,它会创建一个空字典(level)。在for循环中,它将目录名称存储为字典中的键。至于那个键的值,python再次进入函数并搜索一个目录,它就成了该键的值。

但是,关键词典如何记住里面的值?我的意思是,每次python进入函数时都不应该重置/清空吗?

5 个答案:

答案 0 :(得分:7)

没有。函数的每个“实例”都有自己的level副本,level的各个副本之间没有副作用。

拿这个文件夹树:

root
 `-home
    |- lyrae
    |   |- ftp.py
    |   `- http.py
    `- badp

当您在ftp上致电root时,这是(简化的)执行流程:

  • ftp(root)创建一个空level字典
  • ftp(root)枚举子文件夹:(home)
  • ftp(root)选择第一个子文件夹并将目录更改为其中。
  • ftp(root)level[home]设置为当前文件夹中ftp的结果。

  • ftp(home)创建一个空level字典
  • ftp(home)枚举子文件夹:(lyrae, badp)
  • ftp(home)选择第一个子文件夹并将目录更改为其中。
  • ftp(home)level[lyrae]设置为当前文件夹中ftp的结果。

  • ftp(lyrae)创建一个空level字典
  • ftp(lyrae)枚举子文件夹:()
  • ftp(lyrae)超出要解析的子文件夹并返回level

  • ftp(home)完成作业:levels = {'lyrae': {}}
  • ftp(home)更改为下一个文件夹。
  • ftp(home)level[badp]设置为当前文件夹中ftp的结果。

  • ftp(badp)创建一个空level字典
  • ftp(badp)枚举子文件夹:()
  • ftp(badp)超出要解析的子文件夹并返回level

  • ftp(home)完成作业:levels = {'lyrae': {}, 'badp': {}}
  • ftp(home)超出要解析的子文件夹并返回level

  • ftp(root)完成作业:levels = {'home': {'lyrae': {}, 'badp': {}}}
  • ftp(root)超出要解析的子文件夹并返回level

答案 1 :(得分:2)

我认为这些其他答案并不能解释得太多。每次递归进入此函数都会创建一个新的本地级字典。但至关重要的是,它也会归还它。这意味着每次递归的本地版本的级别将成为级别的字典树。一旦递归递归,你就会留下一个互相引用的词典树。这意味着创建的局部变量不会被垃圾收集,因为它有对从最外层函数返回的堆栈中最顶层字典的引用。

答案 2 :(得分:1)

level是一个局部变量。函数的每个“运行”都有自己的变量level,因此变量不会相互干扰。

答案 3 :(得分:1)

level的范围仅限于此功能。即使函数调用自身,也不意味着 函数调用的内部变量(不同的 level)与 this < / em>一个人。

答案 4 :(得分:1)

变量level仅存在于函数的范围内,在函数局部变量的末尾被丢弃,因此对于traverse的每次执行,都会有它自己的level字典。什么都不会被重写或覆盖。