我有一个python的递归方法问题,代码是这样的:
class NodeTree(object):
def __init__(self, name, children):
self.name = name
self.children = children
def count(self):
# 1 + i children's nodes
count = 1
for c in self.children:
count += c.count()
return count
def create_tree(d):
N = NodeTree(d['name'], d['children'])
print N.count()
d1 = {'name':'musica', 'children':[{'name':'rock', 'children':[{'name':'origini','children':[]},
{'name':'rock&roll','children':[]},
{'name':'hard rock', 'children':[]}]},
{'name':'jazz', 'children':[{'name':'origini', 'children':[{'name':'1900', 'children':[]}]},
{'name':'ragtime', 'children':[]}, {'name':'swing', 'children':[]}]}]}
tree = create_tree(d1)
错误是这样的:
count += c.count()
AttributeError: 'dict' object has no attribute 'count'
我尝试过任何东西,但它不起作用。
无论如何,有什么建议吗? 谢谢!
答案 0 :(得分:1)
那是因为Python词典没有count
方法。
如果我们逐行查看代码实际执行的操作,那将会有所帮助。
def count(self): # 1 + i children's nodes count = 1 for c in self.children: ## self.children is a list of dictionaries, so each c is a dictionary count += c.count() ## We are getting .count() of c--which is a dictionary return count
这是因为我们将d1 ['children']作为self.children传递,这是一个词典列表:[<dict>, <dict>, <dict>, ... ]
。
而不是count()
,你应该做的是在字典上调用len
,以获得它拥有的密钥数量,从而成为:
for c in self.children:
count += len(c)
答案 1 :(得分:0)
d['children']
是list of dict
,您可以在d1
字典中看到。
现在,当您在children
NodeTree
中进行迭代时,实际上只有d['children']
{ - 1}},每个元素都会得到dictionary
: -
for c in self.children: // c is a `dict` type here
count += c.count() // there is not attribute as `count` for a `dict`.
因此你得到了那个错误。
答案 2 :(得分:0)
好吧,有一次,create_tree
函数不会递归地构建树。所以你只需要在零级别上添加一个节点,这些子节点只是字典。
以下(修改过的)代码(虽然快速输入和马虎)应该进行递归
树的建造。没有检查您的count
代码,但假设它是正确的,它应该可以工作。
class NodeTree(object):
def __init__(self, name, children):
self.name = name
self.children = children
def count(self):
# 1 + i children's nodes
count = 1
for c in self.children:
count += c.count()
return count
def deep_create_tree(d):
if len(d["children"]) > 0:
chlds = []
for i in d["children"]:
chlds.append(deep_create_tree(i))
else:
chlds = []
n = NodeTree(d["name"], chlds)
return n
d1 = {'name':'musica', 'children':[{'name':'rock', 'children':[{'name':'origini','children':[]},{'name':'rock&roll','children':[]},{'name':'hard rock', 'children':[]}]},{'name':'jazz', 'children':[{'name':'origini', 'children':[{'name':'1900', 'children':[]}]},{'name':'ragtime', 'children':[]}, {'name':'swing', 'children':[]}]}]}
def scan_tree(tr):
print tr.name, tr.count()
for i in tr.children:
scan_tree(i)
tr = deep_create_tree(d1)
scan_tree(tr)
答案 3 :(得分:0)
最好(也是唯一可取的)方法是递归创建节点树。这可以通过两种不同的方式完成,或者让NodeTree.__init__()
递归地初始化所有子项(再次递归地初始化所有子项等),或者可以使create_tree()
函数递归。
我个人使用递归__init__()
,但这是你的电话。
用于创建树结构的递归__init__()
:
def __init__(self, name, children=[]):
self.name = name
self.children = []
for c in children:
self.children.append(
self.__class__(c['name'], c['children']))
这种方式self.children
将包含其他NodeTree
而不是dict
。此外,您不再需要声明空子列表,而不是:
d2 = {'name':'sterile', 'children':[]}
DO
d2 = {'name':'sterile'}
初始化程序会自动将子项设置为[]
如果你想使用递归create_tree()
函数,它也是可能的,也不是一个坏主意。但是,您仍然需要编辑__init__()
- 方法,它不再需要将子项作为参数。或者就像我在这里所做的那样,但是你几乎没有使用它。
# NodeTree
def __init__(self, name, children=None):
self.name = name
if children:
self.children = children
def create_tree(d):
N = NodeTree(d['name'])
for c in d['children']:
N.children.append(create_tree(c))
return N
这将产生基本相同的结果。