问题
I'm using sympy to compute some higher order derivatives of a complicated function expression. I'd like to traverse the AST of the expression, e.g. go through the nodes depth first. How do I do that ?
回答1:
A simple depth-first travel would be like this:
from sympy import pi, sin
from sympy.abc import a,x,y
def depth_first_traverse(expr):
for arg in expr.args:
depth_first_traverse(arg, depth+1, new_marks+'+---', parent_ind=ind)
if len(expr.args) == 0:
# we reached a leaf of the tree
pass # do something with leaf expr
else:
pass # do something with compound expr
depth_first_traverse(sin(a*x*pi+1.5)/y)
With additional parameters, more complex goals can be reached, for example printing the tree in depth-first order while showing how everything fits together:
from sympy import srepr, pi, sin
from sympy.abc import a,x,y
def depth_first_traverse(expr, depth=0, marks='', parent_ind=None):
for ind, arg in enumerate(expr.args):
new_marks = marks.replace('+', '|').replace('-', ' ')
if parent_ind == 0:
new_marks = new_marks[:-4] + ' ' + new_marks[-3:]
depth_first_traverse(arg, depth+1, new_marks+'+---', parent_ind=ind)
if len(expr.args) == 0:
print(marks, end="> ")
print("symbol", srepr(expr))
else:
print(marks, end="+ ")
print("function", expr.func, "had", len(expr.args), "arguments")
print(marks.replace('+', '|').replace('-', ' '))
depth_first_traverse(sin(a*x*pi+1.5)/y)
Output:
+---> symbol Symbol('y')
|
+---> symbol Integer(-1)
|
+---+ function <class 'sympy.core.power.Pow'> had 2 arguments
|
| +---> symbol Float('1.5', precision=53)
| |
| | +---> symbol pi
| | |
| | +---> symbol Symbol('a')
| | |
| | +---> symbol Symbol('x')
| | |
| +---+ function <class 'sympy.core.mul.Mul'> had 3 arguments
| |
| +---+ function <class 'sympy.core.add.Add'> had 2 arguments
| |
+---+ function sin had 1 arguments
|
+ function <class 'sympy.core.mul.Mul'> had 2 arguments
来源:https://stackoverflow.com/questions/59816730/run-through-the-ast-of-an-expression-in-sympy