3

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

4 回答 4

1

那是因为 Python 字典没有count方法。

如果我们逐行检查您的代码实际在做什么,将会有所帮助。

    定义计数(自我):
        # 1 + i 个子节点
        计数 = 1
        for c in self.children: ## self.children 是一个字典列表,所以每个 c 都是一个字典
            count += c.count() ## 我们得到了 c 的 .count()——这是一个字典
        返回计数

这是因为我们将 d1['children'] 作为 self.children 传递,这是一个字典列表:[<dict>, <dict>, <dict>, ... ]

而不是count(),您应该做的是调用len字典,以获取它拥有的键数,从而变为:

    for c in self.children:
        count += len(c)
于 2012-12-04T19:45:42.763 回答
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)
于 2012-12-04T20:23:14.100 回答
0

The best (and the only desirable) way is to have a recursive creation of your node tree. This can be done in two different ways, either make your NodeTree.__init__() recursively init all of the children (which again recursively init all of their children, etc) or you can make your create_tree() function recursive.

I'd personally use recursive __init__(), but it's your call.


Recursive __init__() for creating tree structure:

def __init__(self, name, children=[]):
    self.name = name
    self.children = []
    for c in children:
        self.children.append(
            self.__class__(c['name'], c['children']))

This way self.children will contain other NodeTrees instead of dicts. Also you no longer need to declare empty children list, instead of:

d2 = {'name':'sterile', 'children':[]}

do

d2 = {'name':'sterile'}

And the initializer will automatically set children to []


If you want to use a recursive create_tree() function, it's also possible, and not a bad idea either. However you will still have to edit the __init__() -method, it no longer takes children as parameter. Or as I did here, it does, but you hardly ever use it.

# 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

This will have basically the same results.

于 2012-12-05T12:07:28.347 回答
0

d['children']是 a list of dict,正如您在d1dict 中看到的那样。

现在,当您迭代您的children, in 时NodeTree,这基本上是d['children']唯一的,您将获得dictionary每个元素:-

for c in self.children:  // c is a `dict` type here
    count += c.count()   // there is not attribute as `count` for a `dict`.

因此你得到了那个错误。

于 2012-12-04T19:43:29.273 回答