If I define a simple class like:
class MyObj(object): pass .
I could create a dictionary with several of these objects:
In [819]: d={1:MyObj(), 2:MyObj()}
and then assign attributes to each object
In [820]: d[1].foo=np.arange(3)In [821]: d[1].bar=np.arange(3)In [822]: d[2].foo=np.arange(3)In [823]: d[2].bar=np.arange(3)In [824]: dOut[824]: {1: <__main__.MyObj at 0xaf20cfac>, 2: <__main__.MyObj at 0xaf20c4cc>}
Since I didn't define a repr
or str
the print display isn't very interesting;
In [825]: vars(d[2])Out[825]: {'bar': array([0, 1, 2]), 'foo': array([0, 1, 2])}
I could also made a list with these objects
In [826]: dl = [None, d[1], d[2]]In [827]: dlOut[827]: [None, <__main__.MyObj at 0xaf20cfac>, <__main__.MyObj at 0xaf20c4cc>]In [828]: vars(dl[1])Out[828]: {'bar': array([0, 1, 2]), 'foo': array([0, 1, 2])}
So both a list and dictionary can be indexed (so can an array); but the .foo
syntax is used to access object attributes.
===============
An entirely different way of creating a structure with this kind of access is to use a recarray
- this is a numpy array subclass that allows you to access dtype fields with attribute names
In [829]: R=np.recarray((3,), dtype=[('foo','O'),('bar','O')])In [830]: ROut[830]: rec.array([(None, None), (None, None), (None, None)], dtype=[('foo', 'O'), ('bar', 'O')])In [831]: R[1].foo=np.arange(3)In [832]: R[2].bar=np.arange(4)In [833]: ROut[833]: rec.array([(None, None), (array([0, 1, 2]), None), (None, array([0, 1, 2, 3]))], dtype=[('foo', 'O'), ('bar', 'O')])
Here I defined the fields as taking object dtype, which allows me to assign anything, including other arrays to each attribute. But usually the dtype is something more specific like int, float, string.
I can view the foo
attribute/field for all items in the array R
:
In [834]: R.fooOut[834]: array([None, array([0, 1, 2]), None], dtype=object)In [835]: R['bar']Out[835]: array([None, None, array([0, 1, 2, 3])], dtype=object)
A recarray
has a special method that allows access to the fields via attribute
syntax.