Skip to content

ast Module

The ast module provides classes for working with abstract syntax trees of Python code. It parses Python source into an AST that can be analyzed or modified.

Complexity Reference

Operation Time Space Notes
ast.parse() O(n) O(n) n = source code length
ast.literal_eval() O(n) O(n) Safe evaluation of literals
Tree traversal O(n) O(h) n = nodes, h = max recursion depth
Node creation O(1) O(1) Create single node

Parsing Python Code

Basic Parsing

import ast

# Parse source code - O(n) where n = code length
code = "x = 1 + 2"
tree = ast.parse(code)

# Tree structure - O(1) to access
print(ast.dump(tree))
# Module(body=[Assign(targets=[Name(id='x')], value=BinOp(...))])

Extracting Function Names

import ast

code = """
def hello():
    pass

def world():
    pass
"""

# Parse - O(n)
tree = ast.parse(code)

# Extract functions - O(n) traversal
function_names = [
    node.name 
    for node in ast.walk(tree)
    if isinstance(node, ast.FunctionDef)
]

print(function_names)  # ['hello', 'world']

Safe Literal Evaluation

Evaluate Strings Safely

import ast

# Safe evaluation - O(n)
data = ast.literal_eval("{'name': 'Alice', 'age': 30}")
print(data)  # {'name': 'Alice', 'age': 30}

# Works for lists, tuples, dicts, strings, numbers
numbers = ast.literal_eval("[1, 2, 3, 4, 5]")
print(numbers)  # [1, 2, 3, 4, 5]

# Blocks arbitrary code - safe from injection
try:
    ast.literal_eval("__import__('os').system('rm -rf /')")
except ValueError:
    print("Blocked malicious code")

AST Walking and Traversal

Walking the Entire Tree

import ast

code = """
x = 1
y = x + 2
z = y * 3
"""

tree = ast.parse(code)

# Walk all nodes - O(n) where n = total nodes
for node in ast.walk(tree):
    if isinstance(node, ast.Name):
        print(f"Variable: {node.id}")

# Output:
# Variable: x
# Variable: x
# Variable: y
# Variable: y
# Variable: z

Custom Node Visitor

import ast

class VariableVisitor(ast.NodeVisitor):
    """Visit nodes and collect variables - O(n)"""

    def __init__(self):
        self.variables = set()

    def visit_Name(self, node):
        """Record variable names - O(1)"""
        self.variables.add(node.id)
        self.generic_visit(node)

code = "x = y + z"
tree = ast.parse(code)

visitor = VariableVisitor()
visitor.visit(tree)  # O(n) traversal
print(visitor.variables)  # {'x', 'y', 'z'}

Finding Function Calls

Extract All Function Calls

import ast

code = """
result = max(1, 2, 3)
print(result)
"""

# Parse - O(n)
tree = ast.parse(code)

# Find calls - O(n) traversal
calls = [
    node.func.id
    for node in ast.walk(tree)
    if isinstance(node, ast.Call) 
    and isinstance(node.func, ast.Name)
]

print(calls)  # ['max', 'print']