5

我刚刚读过“isinstance() 被认为有害”,这似乎是合理的。简而言之,它主张避免使用此功能。

好吧,刚才我碰巧正在编写一个程序,该程序接受结构为树的输入,并且需要树的结构信息。没有时间实现 GUI,我强迫用户将其写入配置文件(我知道这是一个糟糕的界面,但时间安排真的很紧)。我的用户技术性很强,但不一定懂python。我选择该文件将包含代表输入树的列表列表(列表列表等),最终元素是树的叶节点。我认为这比将字典的合成器强加给用户要好得多。

我计划递归解析列表如下(省略树结构的使用,让我们简化并说必须在每个叶节点上调用treatLeafNode()):

def parseTree(input):
    if isinstance (input, list):
        for item in input:
            parseTree(item)
    else:
        treatLeafNode(item)

根据这篇文章,我想知道是否有一种简单的方法可以在不使用 isinstance() 的情况下对其进行递归......

有人知道吗?

4

5 回答 5

10

您的情况是我会使用的情况之一isinstance。您的数据结构受到很好的约束,您需要区分列表而不是列表。用来isinstance询问它是否是一个列表。你没有说,但我想字符串可能在你的树的叶子中,并且它们像列表一样是可迭代的,所以用鸭子打字的方式区分它们是很繁琐的。

于 2011-05-04T11:52:11.347 回答
5

你可以使用

def parseTree(input):
    try:
        for item in input:
            parseTree(item)
    except TypeError:
        treatLeafNode(item)

请注意,这也会迭代字符串。

于 2011-05-04T11:40:25.180 回答
2

更好的做法是使用 Node 对象封装您的树结构,该对象可以保存一个值和一个子项列表:

class Node(object):
    def __init__(self, children=[], value=None):
        self.children = children
        self.value = value
    def isLeaf(self):
        return len(self.children) == 0

现在一个节点明确地要么是一个有值的叶子,要么是一个有孩子的元素(从技术上讲,在这个例子中,非叶子节点也可以有值,但是你的应用程序代码可以选择强制非叶子节点永远没有值)。parseTree可以写成:

def parseTree(node):
    if node.isLeaf():
        treatLeafNode(node)
    else:
        for child in node.children:
            parseTree(child)

请注意,这是对树的深度优先搜索。

可能有更好的方法来包装它,所以这parseTree是一种方法Node,但这应该给你一个想法。当然,您仍然有一个问题,即您要求用户编写 Python 代码,该代码是将列表列表作为输入,并将其解析为您需要使用的上述树结构isinstance。也许 yaml 会是更好的描述语言选择,因为用户不能在您的输入中注入任意 Python 代码?

于 2011-05-04T11:49:58.020 回答
0

使用yaml怎么样?您也不必自己进行验证和解析逻辑。

树可能看起来像

- [[aMAN],[sTACK, OVER],[FLOW]]
- [[aMAN1],[sTACK1, OVER1],[FLOW1]]
- [[aMAN2],[sTACK2, OVER2],[FLOW2]]

解析它的代码

import yaml                    
f= open('test.yml')
test = yaml.load(f.read())
print test

输出:

[[['aMAN'], ['sTACK', 'OVER'], ['FLOW']], [['aMAN1'], ['sTACK1', 'OVER1'], ['FLOW1']], [['aMAN2'], ['sTACK2', 'OVER2'], ['FLOW2']]]
于 2011-05-04T12:54:29.787 回答
0

您选择列表列表作为首选树结构是否有原因?我可以想到许多更好的方法来在配置文件中编写一个。假设您正在尝试编码:

a
|-- b
|   |-- c
|   |-- d
|   |   |-- e
|   |   `-- f
|   `-- g
|       `-- h
|-- i
`-- j
    `-- k

怎么样

a: b, i, j
b: c, d, g
d: e, f
g: h
j: k

你可以很容易地把它解析成字典,然后把它连接成一棵树。事实上,我想ConfigParser已经为你做到了。

否则,如何:

a
----b
--------c
--------d
------------e
------------f
--------g
------------h
----i
----j
--------k
于 2011-05-04T13:08:57.187 回答