Python 使用唯一的对象实例创建NumPy
我想使用Python 使用唯一的对象实例创建NumPy,python,python-3.x,numpy,numpy-ndarray,Python,Python 3.x,Numpy,Numpy Ndarray,我想使用numpy.full()创建一个numpy.ndarray完整的自定义类的唯一实例。我目前的尝试是: import numpy as np from custom_class import CustomClass size_x = 4 size_y = 5 my_array = np.full((size_x, size_y), CustomClass('value')) 问题是,当我运行这段代码时,输出是一个numpy.ndarray,其中包含对同一对象的size\uxxsize
numpy.full()
创建一个numpy.ndarray
完整的自定义类的唯一实例。我目前的尝试是:
import numpy as np
from custom_class import CustomClass
size_x = 4
size_y = 5
my_array = np.full((size_x, size_y), CustomClass('value'))
问题是,当我运行这段代码时,输出是一个numpy.ndarray
,其中包含对同一对象的size\ux
xsize\uy
的引用。查看示例输出:
array([[<hexgridcell.HexGridCell object at 0x000001C3B5B18BE0>,
<hexgridcell.HexGridCell object at 0x000001C3B5B18BE0>,
<hexgridcell.HexGridCell object at 0x000001C3B5B18BE0>,
<hexgridcell.HexGridCell object at 0x000001C3B5B18BE0>, ...
数组([,,
,
,
, ...
这里列出的地址都清楚地指向内存中的同一个位置,进一步的调查得出结论,它们确实指向同一个对象实例。我如何才能让一个numpy.ndarray
以这种方式填充唯一的实例?一个示例类:(一个好的问题可以提供类似的内容)
full
在所有插槽中放置相同的内容-当然,因为Foo
只调用一次
In [103]: np.full((2,3), Foo(1,2))
Out[103]:
array([[Foo (1, 2), Foo (1, 2), Foo (1, 2)],
[Foo (1, 2), Foo (1, 2), Foo (1, 2)]], dtype=object)
在前面的问题中,我发现frompyfunc
非常方便,并且比更显式的numpy循环快2倍:
列表方法:
In [107]: [[Foo(i,j) for j in range(4)] for i in range(3)]
Out[107]:
[[Foo (0, 0), Foo (0, 1), Foo (0, 2), Foo (0, 3)],
[Foo (1, 0), Foo (1, 1), Foo (1, 2), Foo (1, 3)],
[Foo (2, 0), Foo (2, 1), Foo (2, 2), Foo (2, 3)]]
一些时间安排:
In [108]: timeit f(np.arange(3)[:,None], np.arange(4))
14.3 µs ± 469 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [109]: timeit [[Foo(i,j) for j in range(4)] for i in range(3)]
7.59 µs ± 18.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [110]: timeit np.array([[Foo(i,j) for j in range(4)] for i in range(3)])
31.3 µs ± 1.69 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
使用对象数组执行一些有用的操作可能会很尴尬。要获得所有元素中的val
,我们必须使用以下内容:
In [115]: np.frompyfunc(lambda obj: obj.val,1,1)(_105)
Out[115]:
array([[(0, 0), (0, 1), (0, 2), (0, 3)],
[(1, 0), (1, 1), (1, 2), (1, 3)],
[(2, 0), (2, 1), (2, 2), (2, 3)]], dtype=object)
或每个元组的第一个元素:
In [116]: np.frompyfunc(lambda obj: obj.val[0],1,1)(_105).astype(int)
Out[116]:
array([[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2]])
使用
numpy.full
将在每个“单元格”中生成一个具有相同对象的数组。对于数字之类的东西,这很好,因为数字1
仍然是一个数字1
。但是,由于您希望在每个单元格中具有不同的类对象,因此需要多次生成每个对象
现在,如果您使用的是自定义类,而不是整型或浮点型等数据类型,那么最好使用普通Python数组。这是因为numpy数组针对此类数据进行了优化。为此,请使用以下生成器
[[CustomClass('value') for j in range(size_x)] for i in range(size_y)]
如果您确实需要使用自定义类,您可能希望为该类内置一些数学函数。可以使用\uuuuu add\uuuuu
类函数实现类似于加法的功能。这将允许将两个数组相加等操作正常进行,而不会引发类型错误。有关的详细信息。以下是一个示例
class CustomClass:
def __init__(self, value):
self.value = value
def __add__(self, second):
return self.value + second.value
使用此定义,下面的代码将添加这些对象的两个numpy数组。但是,这也适用于普通Python数组,因此使用numpy的唯一原因还是用于更大的数据操作,例如调整数组大小和点积乘法
array1 = [[CustomClass(i) for j in range(size_x)] for i in range(size_y)]
array2 = [[CustomClass(j*2) for j in range(size_x)] for i in range(size_y)]
array3 = array1 + array2
print(array3)
full
将相同的对象放在每个位置。您必须为每个元素调用对象创建者fresh,就像创建列表一样。您将第二个参数作为单个值提供,该值将重复。请尝试np.fromfunction(lambda x,y:CustomClass('value'),(size_x,size_y))
为什么不使用列表?为什么在这里使用numpy?在这里使用numpy是没有意义的。几乎可以肯定的是,除非有一些我不知道的非常有趣的技巧,否则你不能做任何矢量化的事情。它将默认为对象
类型,并且不如列表灵活。@juanpa.arrivillaga我想使用numpy对于一些性能/语法方面的优势。实际的应用程序是非常资源密集型的。我看不出fromfunction
有什么帮助。看看array1
。我认为它将是一个CustomClass
和一个数组值
。
class CustomClass:
def __init__(self, value):
self.value = value
def __add__(self, second):
return self.value + second.value
array1 = [[CustomClass(i) for j in range(size_x)] for i in range(size_y)]
array2 = [[CustomClass(j*2) for j in range(size_x)] for i in range(size_y)]
array3 = array1 + array2
print(array3)