Turn your type (bad name!) into a dtype:
In [277]: dt1=np.dtype(type)
In [278]: dt1
Out[278]: dtype([('name', '<U20'), ('bit', '<U20'), ('length', '<U20')])
build a composite dtype. Notice that the format for 'fields' is (dt1,3) - i.e. a subarray consisting of 3 elements of type dt1.
In [279]: dt2=np.dtype({
'names' : ('name','offset','width','fields'),
'formats' : ('U20','U20','U20',(dt1,3))})
In [280]: registers=np.zeros(4,dtype=dt2)
In [281]: registers
Out[281]:
array([('', '', '', [('', '', ''), ('', '', ''), ('', '', '')]),
('', '', '', [('', '', ''), ('', '', ''), ('', '', '')]),
('', '', '', [('', '', ''), ('', '', ''), ('', '', '')]),
('', '', '', [('', '', ''), ('', '', ''), ('', '', '')])],
dtype=[('name', '<U20'), ('offset', '<U20'), ('width', '<U20'), ('fields', [('name', '<U20'), ('bit', '<U20'), ('length', '<U20')], (3,))])
Fill in the names:
In [283]: registers['name']='register_1 register_2 register_3 register_4'.split()
and other 2 fields:
In [284]: registers['offset']=[1,2,3,4]
In [285]: registers['width']=[5,10,15,20]
In [286]: registers
Out[286]:
array([('register_1', '1', '5', [('', '', ''), ('', '', ''), ('', '', '')]),
('register_2', '2', '10', [('', '', ''), ('', '', ''), ('', '', '')]),
('register_3', '3', '15', [('', '', ''), ('', '', ''), ('', '', '')]),
('register_4', '4', '20', [('', '', ''), ('', '', ''), ('', '', '')])],
dtype=[('name', '<U20'), ('offset', '<U20'), ('width', '<U20'), ('fields', [('name', '<U20'), ('bit', '<U20'), ('length', '<U20')], (3,))])
The fields value for registers[0] element can be filled in in the same way:
In [288]: registers[0]['fields']
Out[288]:
array([('', '', ''), ('', '', ''), ('', '', '')],
dtype=[('name', '<U20'), ('bit', '<U20'), ('length', '<U20')])
Now that registers has 4 fields, you can't fill in 3 of them with:
In [289]: registers[0]=('register_1','1','5')
...
ValueError: size of tuple must match number of fields.
The tuple has include all the values needed for the 'fields' field (why did you choose confusing names like this?).
Create an array with dtype dt1, and fill it.
In [290]: regfield=np.zeros(3,dtype=dt1)
In [291]: regfield
Out[291]:
array([('', '', ''), ('', '', ''), ('', '', '')],
dtype=[('name', '<U20'), ('bit', '<U20'), ('length', '<U20')])
In [292]: regfield[0]=('field1',1,10)
In [293]: regfield[1]=('field2',2,20)
In [294]: regfield[2]=('field3',3,30)
Now you can include it as a value in the registers tuple.
In [295]: registers[0]=('register_1','1','5',regfield)
In [296]: registers[0]
Out[296]: ('register_1', '1', '5', [('field1', '1', '10'), ('field2', '2', '20'), ('field3', '3', '30')])
I can replicate the fieldnames to the other registers with:
In [300]: fieldnames=registers['fields']['name'][0]
In [301]: registers['fields']['name']
Out[301]:
array([['field1', 'field2', 'field3'],
['', '', ''],
['', '', ''],
['', '', '']],
dtype='<U20')
In [302]: registers['fields']['name']=fieldnames
In [303]: registers['fields']['name']
Out[303]:
array([['field1', 'field2', 'field3'],
['field1', 'field2', 'field3'],
['field1', 'field2', 'field3'],
['field1', 'field2', 'field3']],
dtype='<U20')
In [304]: registers['fields']
Out[304]:
array([[('field1', '1', '10'), ('field2', '2', '20'), ('field3', '3', '30')],
[('field1', '', ''), ('field2', '', ''), ('field3', '', '')],
[('field1', '', ''), ('field2', '', ''), ('field3', '', '')],
[('field1', '', ''), ('field2', '', ''), ('field3', '', '')]],
dtype=[('name', '<U20'), ('bit', '<U20'), ('length', '<U20')])
New dtype:
In [333]: dt3=np.dtype({
'names' : ('name','offset','width','fields'),
'formats' : ('U20','U20','U20', 'O')})
In [334]: registers=np.zeros(4,dtype=dt3)
In [335]: registers
Out[335]:
array([('', '', '', 0), ('', '', '', 0), ('', '', '', 0), ('', '', '', 0)],
dtype=[('name', '<U20'), ('offset', '<U20'), ('width', '<U20'), ('fields', 'O')])
Assign value to registers[0]. regfield the 3 element array that I defined earlier.
In [337]: registers[0]=('register_1', '1', '5', regfield)
In [338]: registers
Out[338]:
array([ ('register_1', '1', '5', [('field1', '1', '10'), ('field2', '2', '20'), ('field3', '3', '30')]),
('', '', '', 0),
('', '', '', 0),
('', '', '', 0)],
dtype=[('name', '<U20'), ('offset', '<U20'), ('width', '<U20'), ('fields', 'O')])
...
Display is similar to what what we had before, but now each register can have a different number of fields.
We can verify that object in the fields' field ofregisters[0]is theregfield` array by looking at their ids.
In [343]: id(regfield)
Out[343]: 166843840
In [344]: id(registers[0]['fields'])
Out[344]: 166843840
np.objectdtype, but at that point you might as well use a plain Python list, since you lose the performance benefits of numpy arrays by using them to store arbitrary Python objects.