The current implementation of storing nodes and elements in lists as instantiated classes (Elem and Node) seems highly inefficient.
Consider storing the information as numpy arrays or something similar to meshio implementation (or perhaps use the Mesh object from meshio directly if it allows for node and element numbering with gaps?).
Then the Elem and Node can be implemented as pointers to the numpy arrays only (i.e. only instantiated when the user interacts with nodes and elements in code elsewhere).