这是一个功能(归功于用户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进入函数时都不应该重置/清空吗?
答案 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
字典。什么都不会被重写或覆盖。