我正在解析目录。我找到了a snippet here,效果很好,但我似乎无法弄清楚为什么以及如何更新变量dir
的位置。
我想做的是遗漏空文件夹
import os
def get_directory_structure(rootdir):
"""
Creates a nested dictionary that represents the folder structure of rootdir
"""
dir = {}
rootdir = rootdir.rstrip(os.sep)
start = rootdir.rfind(os.sep) + 1
for path, dirs, files in os.walk(rootdir):
folders = path[start:].split(os.sep)
subdir = dict.fromkeys(files)
parent = reduce(dict.get, folders[:-1], dir)
parent[folders[-1]] = subdir
return dir
dir
被设置为与父级相同的值:
parent[folders[-1]] = subdir
为什么?
dir
是可变的,并在reduce
行中作为输入,但不会在那里设置,而是在下一行。
有什么想法吗?
我希望能够省去空文件夹,而宁愿找到一种优雅的方式来做到这一点;作为第二次通过,我应该放弃并浏览字典吗?
[解密后编辑]所以Hans和Adrin指出,reduce实际上让父指向dir,所以它们是同一个对象,并且父更新的任何更新都是dir。
我最后保留了相同的代码,但为了清晰起见重命名了变量:
dir
- > token_dict
folders
- > path_as_list
subdir
- > files_in_dir
parent
- > full_dir
(我最终返回full_dir
)
更多打字,但下次我看,我会立即开始。
答案 0 :(得分:3)
对于任何不太熟悉的人来说,减少字典的一些解释:
在我们讨论片段之前,让我们做一些减少功能。
Reduce will apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
以下是语法:
reduce(function, sequence[, initial]) -> value
如果存在initial,则将其放在计算中序列的项目之前, 当序列为空时用作默认值。
没有首字母:
>>> reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
15
>>>
smiliar to ((((1+2)+3)+4)+5)
初始:
>>> reduce(lambda x, y: x+y, [], 1)
1
>>>
关于字典,关于字典:
首先让我们检查一下dict.get()
方法可以做什么:
>>> d = {'a': {'b': {'c': 'files'}}}
>>> dict.get(d,'a')
{'b': {'c': 'files'}}
>>>
所以,当你把dict.get方法放在reduce中时,会发生这种情况:
>>> d = {'a': {'b': {'c': 'files'}}}
{'b': {'c': 'files'}}
>>> reduce(dict.get, ['a','b','c'], d)
'files'
>>>
类似于:
>>> dict.get(dict.get(dict.get(d,'a'),'b'),'c')
'files'
>>>
当你得到空列表时,你会得到一个空的dict,这是默认值:
>>> reduce(dict.get, [], {})
{}
>>>
让我们回到你的片段:
你的代码段中的dir!= 内置 dir()函数,它只是一个绑定到空字典的名称。
parent = reduce(dict.get, folders[:-1], dir)
因此,在上面的行中,文件夹[: - 1]只是一个目录列表。和dir是empty_dictionary。
如果有任何帮助,请告诉我。
答案 1 :(得分:2)
您正在将dir
传递给reduce
函数。意思是,你将指向对象的指针传递给函数,函数可以改变它。
查看reduce
函数here的实现。请注意以下几行:
accum_value = function(accum_value, x)
此时,accum_value
指向与您initializer
dir
相同的位置,并传递给该函数,在您的情况下为dict.get