【发布时间】:2022-07-20 19:37:54
【问题描述】:
我知道以前有人问过这个问题,我已经看到了答案,但仍然无法弄清楚发生了什么。
我试图根据文件的某些元数据(日期和位置)和一组条件有条件地构建文件夹结构。例如,为了测试我正在使用这些:
COND = [\"Y\", \"m\", \"C\"]
这意味着在文件夹结构中文件需要首先按年份拆分文件,然后是日历月份,然后是原产国。
这是我为测试创建的示例数据:
data = [
[\"111\", dt.datetime(2019, 1, 1), \"Aus\", \"Bri\"],
[\"112\", dt.datetime(2019, 1, 5), \"Aus\", \"Bri\"],
[\"113\", dt.datetime(2019, 2, 10), \"Aus\", \"Mel\"],
[\"114\", dt.datetime(2020, 1, 1), \"Aus\", \"Per\"],
[\"115\", dt.datetime(2020, 1, 10), \"Aus\", \"Per\"],
[\"116\", dt.datetime(2020, 1, 25), \"Aus\", \"Per\"],
[\"117\", dt.datetime(2020, 10, 5), \"My\", \"KL\"],
[\"118\", dt.datetime(2020, 11, 6), \"Ru\", \"Led\"],
[\"119\", dt.datetime(2020, 12, 1), \"Ru\", \"Mos\"],
[\"120\", dt.datetime(2021, 3, 5), \"Aus\", \"Syd\"],
[\"121\", dt.datetime(2021, 5, 1), \"Aus\", \"Mel\"],
[\"122\", dt.datetime(2021, 6, 1), \"Aus\", \"Per\"],
[\"123\", dt.datetime(2021, 11, 1), \"Chi\", \"Bei\"],
[\"124\", dt.datetime(2021, 11, 15), \"Jp\", \"Tok\"],
[\"125\", dt.datetime(2022, 1, 1), \"Aus\", \"Per\"],
[\"126\", dt.datetime(2022, 3, 1), \"Aus\", \"Bri\"],
[\"127\", dt.datetime(2022, 3, 5), \"Aus\", \"Per\"],
[\"128\", dt.datetime(2022, 3, 11), \"My\", \"KL\"],
[\"129\", dt.datetime(2022, 5, 1), \"Aus\", \"Syd\"],
[\"130\", dt.datetime(2022, 8, 8), \"Aus\", \"Bri\"],
]
这些简单的函数执行过滤:
def filter_year(data: list[list[str | dt.datetime]]) -> list[int]:
return {i[1].year for i in data}
def filter_month(data: list[list[str | dt.datetime]]) -> list[int]:
return {i[1].month for i in data}
def filter_day(data: list[list[str | dt.datetime]]) -> list[int]:
return {i[1].day for i in data}
def filter_country(data: list[list[str | dt.datetime]]) -> list[str]:
return {i[2] for i in data}
def filter_city(data: list[list[str | dt.datetime]]) -> list[str]:
return {i[3] for i in data}
condition_dict = {
\"Y\": {\'fun\': filter_year, \'id\': 1 },
\"m\": {\'fun\': filter_month,\'id\': 1 },
\"d\": {\'fun\': filter_day,\'id\': 1},
\"C\": {\'fun\': filter_country, \'id\': 2},
\"c\": {\'fun\': filter_city, \'id\': 3 }
我正在尝试使用任意顺序树自动构建结构。节点上的数据拆分工作正常:
from typing import Any
from pathlib import Path
from dataclasses import dataclass, field
@dataclass
class Node:
folder: Path
metadata: list[list[Any]] = field(default_factory=list)
conditions: list[str] = field(default_factory=list)
@property
def children(self) -> list[\'Node\']:
if len(self.conditions) == 0:
return []
current_condition = self.conditions[0]
fun = condition_dict[current_condition][\'fun\']
fnames: list[int | str] = fun(self.metadata)
children_data = {str(n): {} for n in fnames}
for f in fnames:
children_data[str(f)][\'folder\'] = self.folder / str(f)
children_data[str(f)][\'conditions\'] = self.conditions[1:]
if current_condition == \'Y\':
children_data[str(f)][\'metadata\'] = [i for i in self.metadata if i[1].year == f]
elif current_condition == \'m\':
children_data[str(f)][\'metadata\'] = [i for i in self.metadata if i[1].month == f]
elif current_condition == \'d\':
children_data[str(f)][\'metadata\'] = [i for i in self.metadata if i[1].day == f]
elif current_condition == \'C\':
children_data[str(f)][\'metadata\'] = [i for i in self.metadata if i[2] == f]
elif current_condition == \'c\':
children_data[str(f)][\'metadata\'] = [i for i in self.metadata if i[3] == f]
return [Node(**i) for i in children_data.values()]
现在,我正在尝试遍历我使用此处答案的修改版本的树(Traverse Non-Binary Tree)
@dataclass
class Tree:
def traverse(self, root: Node):
r = root.children
if not r or len(root.conditions) == 0:
print(\'The end of subtree:\', root.folder)
else:
for child in r:
print(\'\\n\'.join(str(i.folder) for i in r))
if isinstance(child, Node):
for x in self.traverse(child):
print(str(x.folder))
else:
print(child)
但是当我在几次正确输出后尝试使用我的数据时,我总是遇到错误NoneType is not iterable:
n = Node(folder=Path(\'/home\'), metadata=data, conditions=COND)
tree = Tree()
tree.traverse(n)
输出:
/home/2019
/home/2020
/home/2021
/home/2022
/home/2019/1
/home/2019/2
/home/2019/1/Aus
The end of subtree: /home/2019/1/Aus
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/home/pavel/python/photo_manager/temp/tree_test.ipynb Cell 4 in <cell line: 4>()
1 n = Node(folder=Path(\'/home\'), metadata=data, conditions=COND)
3 tree = Tree()
----> 4 tree.traverse(n)
/home/pavel/python/photo_manager/temp/tree_test.ipynb Cell 4 in Tree.traverse(self, root)
45 print(\'\\n\'.join(str(i.folder) for i in r))
46 if isinstance(child, Node):
---> 47 for x in self.traverse(child):
48 print(str(x.folder))
49 else:
/home/pavel/python/photo_manager/temp/tree_test.ipynb Cell 4 in Tree.traverse(self, root)
45 print(\'\\n\'.join(str(i.folder) for i in r))
46 if isinstance(child, Node):
---> 47 for x in self.traverse(child):
48 print(str(x.folder))
49 else:
/home/pavel/python/photo_manager/temp/tree_test.ipynb Cell 4 in Tree.traverse(self, root)
45 print(\'\\n\'.join(str(i.folder) for i in r))
46 if isinstance(child, Node):
---> 47 for x in self.traverse(child):
48 print(str(x.folder))
49 else:
TypeError: \'NoneType\' object is not iterable
我不明白为什么会发生这种情况,因为我相信我提防了 NoneType。出于某种原因,我只到达一个子树的末尾,但没有遍历其他子树。我在这里做错了什么?
标签: python tree tree-traversal