如何在 Python 中找到 ast 节点及其子节点
How to find ast nodes and its sub nodes in Python
我正在尝试遍历 Python 中的 ast 节点,以获取所有分配节点的值节点的名称 ID。 Ast.walk() 方法随机给我节点。
假设:仅用于分配节点
for node in ast.walk(tree):
if isinstance(node,(ast.Assign)):
if isinstance(node.value,(ast.Name)):
print('Assign Value:-','lineno: ',node.value.lineno,' id :',node.value.id)
if isinstance(node.value,(ast.Tuple)):
for i in range(len(node.value.elts)):
if isinstance(node.value.elts[i],(ast.Name)):
print('Assign Value:-','lineno: ',node.value.elts[i].lineno,' id :',node.value.elts[i].id)
在这里,有时ast会在值节点内给出BinOps、Call等。我必须在值节点中获取 Name.id。
Ex: a,b = (c+d), e --> 预期值应该是 c,d,e..但我只得到 e 。另外,如何将 (c,d) 标记为目标 'a' .
可以从分配节点获取目标。
您可以 walk
原始 ast
,并且对于每个 ast.Assign
,递归提取目标名称和关联值 id
s:
import ast
def names(a):
return [i.id for i in ast.walk(a) if isinstance(i, ast.Name)]
def bindings(target, value):
if isinstance(target, ast.Name):
yield [target.id, names(value)]
elif isinstance(target, (ast.List, ast.Tuple)):
if not isinstance(value, (ast.List, ast.Tuple)):
yield [tuple(names(target)), names(value)]
else:
for a, b in zip(target.elts, value.elts):
yield from bindings(a, b)
def assign_bindings(s):
return [dict(bindings(i.targets[0], i.value)) for i in ast.walk(ast.parse(s))
if isinstance(i, ast.Assign)]
上面的代码允许您传递 assign_bindings
一个源字符串,该字符串具有带解包的赋值语句、单个名称绑定、元组、表达式等:
print(assign_bindings('a, b = (c+d), e'))
print(assign_bindings('a, [b, c, [d, [e]]] = [n1, [n2, n3, [n4, [n5]]]]'))
print(assign_bindings('vals = func(a + b)'))
输出:
[{'a': ['c', 'd'], 'b': ['e']}]
[{'a': ['n1'], 'b': ['n2'], 'c': ['n3'], 'd': ['n4'], 'e': ['n5']}]
[{'vals': ['func', 'a', 'b']}]
我正在尝试遍历 Python 中的 ast 节点,以获取所有分配节点的值节点的名称 ID。 Ast.walk() 方法随机给我节点。
假设:仅用于分配节点
for node in ast.walk(tree):
if isinstance(node,(ast.Assign)):
if isinstance(node.value,(ast.Name)):
print('Assign Value:-','lineno: ',node.value.lineno,' id :',node.value.id)
if isinstance(node.value,(ast.Tuple)):
for i in range(len(node.value.elts)):
if isinstance(node.value.elts[i],(ast.Name)):
print('Assign Value:-','lineno: ',node.value.elts[i].lineno,' id :',node.value.elts[i].id)
在这里,有时ast会在值节点内给出BinOps、Call等。我必须在值节点中获取 Name.id。
Ex: a,b = (c+d), e --> 预期值应该是 c,d,e..但我只得到 e 。另外,如何将 (c,d) 标记为目标 'a' .
可以从分配节点获取目标。
您可以 walk
原始 ast
,并且对于每个 ast.Assign
,递归提取目标名称和关联值 id
s:
import ast
def names(a):
return [i.id for i in ast.walk(a) if isinstance(i, ast.Name)]
def bindings(target, value):
if isinstance(target, ast.Name):
yield [target.id, names(value)]
elif isinstance(target, (ast.List, ast.Tuple)):
if not isinstance(value, (ast.List, ast.Tuple)):
yield [tuple(names(target)), names(value)]
else:
for a, b in zip(target.elts, value.elts):
yield from bindings(a, b)
def assign_bindings(s):
return [dict(bindings(i.targets[0], i.value)) for i in ast.walk(ast.parse(s))
if isinstance(i, ast.Assign)]
上面的代码允许您传递 assign_bindings
一个源字符串,该字符串具有带解包的赋值语句、单个名称绑定、元组、表达式等:
print(assign_bindings('a, b = (c+d), e'))
print(assign_bindings('a, [b, c, [d, [e]]] = [n1, [n2, n3, [n4, [n5]]]]'))
print(assign_bindings('vals = func(a + b)'))
输出:
[{'a': ['c', 'd'], 'b': ['e']}]
[{'a': ['n1'], 'b': ['n2'], 'c': ['n3'], 'd': ['n4'], 'e': ['n5']}]
[{'vals': ['func', 'a', 'b']}]