In [1]: class TestClass():
...: objectarray=np.empty([10, 1], dtype=np.object) ## static array holding all class o
...: bjects
...: def __init__(self,name,position):
...: self.name=name
...: self.position=position
...: self.intmember= 5
...: self.floatmember=3.4
...: self.arraymember= np.zeros([5, 5]) ## another array which is a member of the c
...: lass
...: TestClass.objectarray[position]=self
...:
In [2]: testobj1 = TestClass('test1',5)
Как определено testobj1
имеет атрибут intmember
:
In [3]: testobj1
Out[3]: <__main__.TestClass at 0x7fceba8acef0>
In [4]: testobj1.intmember
Out[4]: 5
Этот объект также поместил себя в массив класса:
In [5]: TestClass.objectarray
Out[5]:
array([[None],
[None],
[None],
[None],
[None],
[<__main__.TestClass object at 0x7fceba8acef0>],
[None],
[None],
[None],
[None]], dtype=object)
Поскольку это Для двумерного массива мы используем двумерную индексацию для ссылки на элемент:
In [8]: TestClass.objectarray[5,0]
Out[8]: <__main__.TestClass at 0x7fceba8acef0>
In [9]: TestClass.objectarray[5,0].intmember
Out[9]: 5
Доступ с помощью [5]
только для индексации первого измерения; объект все еще встроен в массив:
In [10]: TestClass.objectarray[5]
Out[10]: array([<__main__.TestClass object at 0x7fceba8acef0>], dtype=object)
Не думаю, что создание массива (10,1) помогло; простой 1d был бы так же хорош:
objectarray=np.empty([10], dtype=np.object)
или просто список:
In [12]: class TestClass():
...: objectarray=[None]*10
...: def __init__(self,name,position):
...: self.name=name
...: self.position=position
...: self.intmember= 5
...: self.floatmember=3.4
...: self.arraymember= np.zeros([5, 5]) ## another array which is a member of the
...: class
...: TestClass.objectarray[position]=self
...:
In [13]: testobj1 = TestClass('test1',5)
In [14]: testobj1
Out[14]: <__main__.TestClass at 0x7fceac25f5c0>
In [15]: testobj1.objectarray
Out[15]:
[None,
None,
None,
None,
None,
<__main__.TestClass at 0x7fceac25f5c0>,
None,
None,
None,
None]
In [16]: testobj1.objectarray[5]
Out[16]: <__main__.TestClass at 0x7fceac25f5c0>
In [17]: testobj1.objectarray[5].intmember
Out[17]: 5
Доступ к элементу списка быстрее, чем делать то же самое для массива объектов:
In [18]: timeit Out[5][5,0].intmember
149 ns ± 0.00964 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [19]: timeit Out[15][5].intmember
90.5 ns ± 0.0478 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
frompyfun c
Я рекомендовал np.frompyfunc
в качестве удобного, если не быстрого, способа доступа к массивам типа d объекта или иной работы с ними. Например,
Функция для извлечения значения intmember
, если оно присутствует:
In [28]: def getval(item):
...: try:
...: return item.intmember
...: except AttributeError:
...: return None
, примененное к массиву объектов:
In [29]: np.frompyfunc(getval,1,1)(Out[5])
Out[29]:
array([[None],
[None],
[None],
[None],
[None],
[5],
[None],
[None],
[None],
[None]], dtype=object)
, примененное к списку:
In [30]: np.frompyfunc(getval,1,1)(Out[15])
Out[30]:
array([None, None, None, None, None, 5, None, None, None, None],
dtype=object)
время:
In [31]: timeit np.frompyfunc(getval,1,1)(Out[15])
14.6 µs ± 187 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [32]: timeit np.frompyfunc(getval,1,1)(Out[5])
9.53 µs ± 54 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [33]: [getval(i) for i in Out[15]]
Out[33]: [None, None, None, None, None, 5, None, None, None, None]
In [34]: timeit [getval(i) for i in Out[15]]
6.53 µs ± 93.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
понимание списка в списке самое быстрое.