Python 3.x 获取Python中抽象语法树的深度

Python 3.x 获取Python中抽象语法树的深度,python-3.x,abstract-syntax-tree,depth,Python 3.x,Abstract Syntax Tree,Depth,我试图在Python 3.7中使用抽象语法树,我使用Python库中的ast库。我想知道使用ast.parse创建的树的深度。我在库中没有找到任何用于此的内置函数 我用这个玩具的例子试过: py_ast = ast.parse('''pd.read_json(elevations)''') def depth_ast(tree, depth=0): branches_depth = [] if isinstance(tree, ast.AST): for i,

我试图在Python 3.7中使用抽象语法树,我使用Python库中的ast库。我想知道使用
ast.parse
创建的树的深度。我在库中没有找到任何用于此的内置函数

我用这个玩具的例子试过:

py_ast = ast.parse('''pd.read_json(elevations)''')

def depth_ast(tree, depth=0):
    branches_depth = []
    if isinstance(tree, ast.AST):
        for i, field in enumerate(tree._fields):
            child = getattr(tree, field)
            depth += 1
            branch_depth = depth_ast(child, depth)
            branches_depth.append(branch_depth)
    elif isinstance(tree, list):  # multiple cardinality
        if tree == []:
            return depth
        else:
            for i, arg in enumerate(tree):
                depth += 1
                branch_depth = depth_ast(arg, depth)
                branches_depth.append(branch_depth)
            return max(branches_depth)
    else:  # primitives
        return depth
    try:
        return max(branches_depth)
    except:
        return depth

print(depth_ast(py_ast))

这段代码的深度是8,而它应该是6(
Module->Expr->Call->Attribute->Name->pd'
),我不明白为什么。

这里有两个相关的概念:

  • 树中节点的深度,即该节点与树根之间的距离,以及
  • 树中节点的高度(更准确地说,是在该节点上生根的子树的高度),它是从该节点到任何后代的最大距离
树的深度是任何节点的最大深度;树的高度就是根的高度。应该清楚的是,这些值是相同的

当然可以递归地遍历树,通过递归传递当前深度。如果出于某种原因,您需要用每个ast节点的深度对其进行注释,这甚至可能非常有用。但如果您只想计算树的高度,有一个更自然的递归解决方案:

# This is a generic recursive algorithm
def height(node):
    return 1 + max((height(child) for child in children(node)),
                   default = 0)
这取决于一个函数的存在,该函数在一个节点的子节点上迭代,上面称为
children
。对于Python ast的特定情况,我们可以使用
ast
模块的便利函数,
iter\u child\u节点

def depth_ast(根):
返回1+最大值((深度)最小值(子级)
对于ast.iter\u child\u节点(根节点)中的子节点,
默认值=0)
#或:
def深度(根):
返回1+max(map(depth\u ast,ast.iter\u child\u nodes(root)),
默认值=0)

节点的深度比其子节点的最大深度大一个。这不是你正在计算的。(为什么在循环中重复递增
depth
?为什么还要麻烦将其作为参数传递?)我在循环中递增depth,因为可能有几个子级。我认为在递归函数中,我必须跟踪深度。你建议怎么做?但是所有的孩子都是平等的。它们不会越来越深。(我的建议在我的第一条评论中。)