In my opinion the itertree package (I'm the author) provides a good solution for the problem.
First we build a tree representing the given tuple structure:
>>>from itertree import *
>>>root=iTree('root')
>>># we must use some helper tags ("sub","sub2","sub3") to fill the tree
>>>root += iTree('sub')
>>>root += iTree('sub')
>>>root += iTree('sub',data=7)
>>>root += iTree('sub')
>>>root[0] += iTree('sub2')
>>>root[0][0] += iTree('sub3', data=1)
>>>root[0][0] += iTree('sub3', data=2)
>>>root[0] += iTree('sub2', data=3)
>>>
>>>root[1] += iTree('sub2', data=4)
>>>root[1] += iTree('sub2')
>>>root[1][0] += iTree('sub3', data=5)
>>>root[1][0] += iTree('sub3', data=6)
>>>
>>>root[3] += iTree('sub2', data=8)
>>>root[3] += iTree('sub2', data=9)
>>>root[3] += iTree('sub2', data=10)
The tree content looks like this:
>>>root.render()
iTree('root')
└──iTree('sub')
└──iTree('sub2')
└──iTree('sub3', data=1)
└──iTree('sub3', data=2)
└──iTree('sub2', data=3)
└──iTree('sub')
└──iTree('sub2', data=4)
└──iTree('sub3', data=5)
└──iTree('sub3', data=6)
└──iTree('sub2')
└──iTree('sub', data=7)
└──iTree('sub')
└──iTree('sub2', data=8)
└──iTree('sub2', data=9)
└──iTree('sub2', data=10)
The item access is now possible via index:
>>>print(root[0][0][0].d_get())
1
>>># or
>>>print(root.get_deep([1, 0, 1]).d_get())
6
The item itself also knows his index-path:
>>>print(root.get_deep([0,0,1]).idx_path)
[0, 0, 1]
A filtered access to the data content is possible too:
>>>item_filter=Filter.iTFilterData(data_value=iTInterval(2,5))
>>>for i in root.iter_all(item_filter):
>>> print(i)
iTree("'sub2'", data=3, subtree=[])
iTree("'sub2'", data=4, subtree=[iTree("'sub3'", data=5, subtree=[]), iTree("'sub3'", data=6, subtree=[])])