python中递归方法的AttributeError

时间:2012-12-04 19:37:46

标签: python exception methods recursion attributeerror

我有一个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'

我尝试过任何东西,但它不起作用。

无论如何,有什么建议吗? 谢谢!

4 个答案:

答案 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

这将产生基本相同的结果。