How to Copy a Node in treelib: Shallow vs Deep Clone Methods

Copy a node in treelib by instantiating a new Node object with the original node's tag and data, using copy.deepcopy() for independent data or direct assignment for shared references.

The treelib library (maintained in the caesar0301/treelib repository) provides tree data structure management for Python, but it does not expose a dedicated Node.copy() method. Instead, developers must understand how to copy a node in treelib through constructor patterns and relationship cloning techniques.

Understanding Node Structure and Instantiation

In treelib/node.py, the Node class defines its constructor at lines 88-94. The __init__ method accepts tag, identifier, and data parameters, making it the primary mechanism for node duplication. Since there is no built-in copy utility, creating a new instance with the same attributes is the canonical approach to copy a node in treelib.

Shallow Copy vs Deep Copy

When you copy a node in treelib, you must decide whether the new node should share the same data object or maintain an independent copy.

Shallow Copy Method

A shallow copy creates a new node that references the same data object as the original. Mutations to the data will affect both nodes.

from treelib import Node

# Original node with mutable data

original = Node(tag="Parent", identifier="node_1", data={"value": 10})

# Shallow copy: shares the data reference

shallow_copy = Node(
    tag=original.tag,
    identifier="node_1_copy",
    data=original.data  # Same dict object

)

Deep Copy Method

A deep copy creates a completely independent node with duplicated data. This prevents side effects when modifying either node's payload.

from treelib import Node
import copy

# Deep copy: independent data copy

deep_copy = Node(
    tag=original.tag,
    identifier="node_1_deep",
    data=copy.deepcopy(original.data)  # New dict object

)

According to the test suite in tests/test_node_comprehensive.py (lines 33-34), using copy.deepcopy() is the recommended pattern for ensuring data isolation when you copy a node in treelib.

Copying Node Relationships Between Trees

When working with multiple tree instances, copying a node requires transferring its parent-child relationships. The Node class provides the clone_pointers method (implemented in treelib/node.py, lines 69-95) to map a node's connections from one tree to another.

from treelib import Tree, Node

# Source tree

source_tree = Tree()
source_tree.create_node("Root", "root")
source_tree.create_node("Child", "child", parent="root", data={"key": "value"})

# Target tree

target_tree = Tree(identifier="target_tree")
target_tree.create_node("New Root", "new_root")

# Copy node and its relationships

node_to_copy = source_tree.get_node("child")
new_node = Node(
    tag=node_to_copy.tag,
    identifier="copied_child",
    data=copy.deepcopy(node_to_copy.data)
)

target_tree.add_node(new_node, parent="new_root")
new_node.clone_pointers(
    old_tree_id=source_tree.identifier,
    new_tree_id=target_tree.identifier
)

Copying Entire Subtrees

For duplicating complete tree structures rather than individual nodes, the Tree class constructor accepts another tree instance with the deep parameter. This functionality, located in treelib/tree.py (lines 177-188), handles the recursive copying of all nodes and their data.

from treelib import Tree

# Original tree with nested structure

original_tree = Tree()
original_tree.create_node("A", "a", data={"count": 1})
original_tree.create_node("B", "b", parent="a", data={"count": 2})
original_tree.create_node("C", "c", parent="b", data={"count": 3})

# Deep copy of entire tree

copied_tree = Tree(original_tree, deep=True)

# Verify independence

original_tree.get_node("b").data["count"] = 999
print(copied_tree.get_node("b").data["count"])  # Output: 2 (unchanged)

Summary

  • treelib does not provide a Node.copy() method; you copy a node in treelib by instantiating a new Node with the original's attributes.
  • Use Node(tag, identifier, data=original.data) for shallow copies that share data references.
  • Use copy.deepcopy(original.data) in the constructor for deep copies with independent data.
  • Transfer parent-child relationships between trees using node.clone_pointers(old_tree_id, new_tree_id).
  • Copy entire tree structures using Tree(source_tree, deep=True) as implemented in treelib/tree.py.

Frequently Asked Questions

How do I copy a node in treelib without sharing the same data object?

Pass a deep copy of the data to the Node constructor using Python's copy module: Node(tag, new_id, data=copy.deepcopy(original.data)). This creates an independent copy where modifications to the new node's data do not affect the original node.

Is there a built-in method to duplicate a node with all its children?

While individual nodes lack a built-in copy method, you can duplicate an entire subtree—including all descendants—by using the Tree class constructor with deep=True: new_tree = Tree(original_tree, deep=True). This recursively copies every node and its data as implemented in treelib/tree.py.

How do I preserve parent-child relationships when moving a copied node to a different tree?

After creating the new node and adding it to the target tree, call clone_pointers(old_tree_id, new_tree_id) on the node instance. This method, defined in treelib/node.py, maps the original tree's pointer references to the new tree's identifier.

What is the difference between shallow and deep copying in treelib?

A shallow copy shares the same data object reference between the original and new node, meaning changes to node.data affect both instances. A deep copy creates an independent duplicate of the data object using copy.deepcopy(), ensuring complete isolation between the original node and its copy.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →