如何在python中创建具有属性的嵌套文件夹?
我是一个初学者程序员,我刚刚开始学习嵌套列表和字典。我的任务是创建一个文件系统,包括类目录及其属性如何在python中创建具有属性的嵌套文件夹?,python,recursion,nested,Python,Recursion,Nested,我是一个初学者程序员,我刚刚开始学习嵌套列表和字典。我的任务是创建一个文件系统,包括类目录及其属性 class Directory: def __init__(self, name: str, parent: Optional['Directory'], children: List[Optional['Directory']]): self.name = name self.parent = parent self.children =
class Directory:
def __init__(self, name: str, parent: Optional['Directory'], children: List[Optional['Directory']]):
self.name = name
self.parent = parent
self.children = children
我应该构建一个函数来递归地创建这个文件系统,给定根目录和字典中的目录。父目录是一个目录,其中包含当前目录作为其子目录之一。任何没有子目录的目录都应该是空目录
"root": ["dirA", "dirB"],
"dirA": ["dirC"],
"dirC": ["dirH", "dirG"],
"dirB": ["dirE"]
"dirG": ["dirX", "dirY"]}
我一直在尝试这样做,我想我知道如何递归地创建目录,但是我不知道在没有任何额外导入的情况下在dir.parent位置放置什么。对于root,并没有问题,因为它只是过程中的一部分,我不知道如何将子级的父级(应该是目录)作为他的一个属性,因为我将递归地从那个里开始。你知道怎么做吗?以下是我目前掌握的代码:
def create_system(system: Dict[str, List[str]], parent_children: List[str]) -> Optional[List[Optional['Directory']]]:
children: List[Optional['Directory']] = []
for child in parent_children:
if child in system.keys():
children.append(Directory(child, parent, create_system(system, list(system.get(child)))))
else:
children.append(Directory(child, parent, []))
return children
def root(system: Dict[str, List[str]]) -> Optional['Directory']:
return Directory("root", None, create_system(system, list(system.get("root"))))
谢谢您的回复 您的目标是转换字典
system = {
"root": ["dirA", "dirB"],
"dirA": ["dirC"],
"dirC": ["dirH", "dirG"],
"dirB": ["dirE"]
"dirG": ["dirX", "dirY"]
}
进入以下树:
root
/ \
dirA dirB
/ \
dirC dirE
/ \
dirH dirG
/ \
dirX dirY
希望很明显,流程的返回值可以是根。为了保证仅在创建父文件夹后才能访问每个文件夹,可以使用基于堆栈的BFS方法,也可以使用递归DFS方法
让我们来看一个简单的BFS方法:
def create_system_bfs(system):
root = Directory('root', None, [])
stack = [root] # in practice, use collections.deque([root])
while stack:
current = stack.pop(0)
for child in system.get(current.name, []):
d = Directory(child, current, [])
current.children.append(d)
stack.append(d)
return root
DFS版本可能类似于:
def create_system_dfs(system):
def create_node(name, parent):
d = Directory(name, parent, [])
d.children = [create_node(child, d) for child in system.get(name, [])]
return d
return create_node('root', None)
请记住,还有其他可能的方法。在这两种情况下,
create\u root
方法完全没有必要。BFS方法仅受可用堆内存的限制。DFS方法也可能受到堆栈大小的限制。您的目标是转换字典
system = {
"root": ["dirA", "dirB"],
"dirA": ["dirC"],
"dirC": ["dirH", "dirG"],
"dirB": ["dirE"]
"dirG": ["dirX", "dirY"]
}
进入以下树:
root
/ \
dirA dirB
/ \
dirC dirE
/ \
dirH dirG
/ \
dirX dirY
希望很明显,流程的返回值可以是根。为了保证仅在创建父文件夹后才能访问每个文件夹,可以使用基于堆栈的BFS方法,也可以使用递归DFS方法
让我们来看一个简单的BFS方法:
def create_system_bfs(system):
root = Directory('root', None, [])
stack = [root] # in practice, use collections.deque([root])
while stack:
current = stack.pop(0)
for child in system.get(current.name, []):
d = Directory(child, current, [])
current.children.append(d)
stack.append(d)
return root
DFS版本可能类似于:
def create_system_dfs(system):
def create_node(name, parent):
d = Directory(name, parent, [])
d.children = [create_node(child, d) for child in system.get(name, [])]
return d
return create_node('root', None)
请记住,还有其他可能的方法。在这两种情况下,
create\u root
方法完全没有必要。BFS方法仅受可用堆内存的限制。DFS方法也可能受到堆栈大小的限制。在将所有的类都纠结在一起之前,我们可以用普通函数来思考-
def paths(t, init="root"):
def loop(q, path):
if isinstance(q, dict):
for (dir, v) in q.items():
yield from loop(v, [*path, dir])
elif isinstance(q, list):
for dir in q:
yield from loop \
( t[dir] if dir in t else None
, [*path, dir]
)
else:
yield "/".join(path)
yield from loop(t[init], ["."])
使用路径
很容易,只需在输入
树上调用它即可-
输入={
“根”:[“dirA”,“dirB”],
“dirA”:[“dirC”],
“dirC”:[“dirH”,“dirG”],
“dirB”:[“dirE”],
“dirG”:[“dirX”,“dirY”]
}
对于路径中的路径(输入):
打印(路径)
/dirA/dirC/dirH
/dirA/dirC/dirG/dirX
/dirA/dirC/dirG/dirY
/可怕/可怕
使用路径
可以轻松创建所需的目录-
导入操作系统
对于路径中的路径(输入):
os.makedirs(路径)
在把所有的东西都纠结在类中之前,我们可以用一个普通函数来思考-
def paths(t, init="root"):
def loop(q, path):
if isinstance(q, dict):
for (dir, v) in q.items():
yield from loop(v, [*path, dir])
elif isinstance(q, list):
for dir in q:
yield from loop \
( t[dir] if dir in t else None
, [*path, dir]
)
else:
yield "/".join(path)
yield from loop(t[init], ["."])
使用路径
很容易,只需在输入
树上调用它即可-
输入={
“根”:[“dirA”,“dirB”],
“dirA”:[“dirC”],
“dirC”:[“dirH”,“dirG”],
“dirB”:[“dirE”],
“dirG”:[“dirX”,“dirY”]
}
对于路径中的路径(输入):
打印(路径)
/dirA/dirC/dirH
/dirA/dirC/dirG/dirX
/dirA/dirC/dirG/dirY
/可怕/可怕
使用路径
可以轻松创建所需的目录-
导入操作系统
对于路径中的路径(输入):
os.makedirs(路径)
这是一个学习可重用模块和交互递归的机会。此答案中的此解决方案解决了您的特定问题,而无需对中编写的模块进行任何修改。这种方法的显著优点是
树
对节点形状没有任何了解,并允许您定义任何输出形状
下面我们使用带有名称
、父属性
和子属性的普通dict
创建一个树<代码>树
不会为您做出此选择。如果需要,可以使用不同的结构或自定义类-
from tree import tree
input = {
None: ["dirA", "dirB"],
"dirA": ["dirC"],
"dirC": ["dirH", "dirG"],
"dirB": ["dirE"],
"dirG": ["dirX", "dirY"]
}
result = tree \
( flatten(input)
, parent
, lambda node, children:
dict \
( name=name(node)
, parent=parent(node)
, children=children(name(node))
)
)
print(result)
[
{
“姓名”:“迪拉”,
“家长”:无,
“儿童”:[
{
“名称”:“dirC”,
“家长”:“迪拉”,
“儿童”:[
{
“姓名”:“dirH”,
“父项”:“dirC”,
“儿童”:[]
},
{
“姓名”:“迪格”,
“父项”:“dirC”,
“儿童”:[
{
“名称”:“dirX”,
“父项”:“dirG”,
“儿童”:[]
},
{
“姓名”:“迪里”,
“父项”:“dirG”,
“儿童”:[]
}
]
}
]
}
]
},
{
“名称”:“dirB”,
“家长”:无,
“儿童”:[
{
“名字”:“可怕”,
“父项”:“dirB”,
“儿童”:[]
}
]
}
]
为了使用树
,我们定义了一种展平
输入节点的方法-
def展平(t):
seq=链从可匹配\
(图(λ:(,k),v)
对于input.items()中的(k,v)
)
退货清单(seq)
打印(展平(输入))
[('dirA',无)
,('dirB',无)
,('dirC','dirA')
,('dirH','dirC')
,('dirG','dirC')
,(“可怕的”、“肮脏的”)
,('dirX','dirG')
,('dirY','dirG')
]
并定义了主键和外键。这里我们使用name
和parent
,但您可以选择您喜欢的名称-
def名称(t):
返回t[0]
def父级(t):
返回t[1]
要了解有关
树模块及其一些优点的更多信息,请参阅这是一个了解可重用模块和交互递归的机会。此答案中的此解决方案无需任何修改即可解决您的特定问题