Numpy对象数组

ast*_*rog 9 python arrays numpy class

我最近在使用eg创建Numpy对象数组时遇到了问题

a = np.array([c], dtype=np.object)
Run Code Online (Sandbox Code Playgroud)

其中c是某个复杂类的实例,在某些情况下,Numpy尝试访问该类的某些方法.但是,做:

a = np.empty((1,), dtype=np.object)
a[0] = c
Run Code Online (Sandbox Code Playgroud)

解决了这个问题.我很好奇内部这两者之间的区别.为什么在第一种情况下Numpy会尝试访问某些属性或方法c

编辑:为了记录,这里是演示该问题的示例代码:

import numpy as np

class Thing(object):

    def __getitem__(self, item):
        print "in getitem"

    def __len__(self):
        return 1

a = np.array([Thing()], dtype='object')
Run Code Online (Sandbox Code Playgroud)

这打印出getitem两次.基本上如果__len__在类中存在,那么这就是人们可能遇到意外行为的时候.

don*_*mus 11

在第一种情况下a = np.array([c], dtype=np.object),numpy对预期数组的形状一无所知.

例如,当您定义时

d = range(10)
a = np.array([d])
Run Code Online (Sandbox Code Playgroud)

那么你期望numpy根据长度来确定形状d.

因此,在您的情况下,numpy将尝试查看是否len(c)已定义,如果已定义,则访问cvia 的元素c[i].

您可以通过定义诸如的类来查看效果

class X(object):
    def __len__(self): return 10
    def __getitem__(self, i): return "x" * i
Run Code Online (Sandbox Code Playgroud)

然后

print numpy.array([X()], dtype=object)
Run Code Online (Sandbox Code Playgroud)

产生

[[ x xx xxx xxxx xxxxx xxxxxx xxxxxxx xxxxxxxx xxxxxxxxx]]
Run Code Online (Sandbox Code Playgroud)

相反,在你的第二种情况下

a = np.empty((1,), dtype=np.object)
a[0] = c
Run Code Online (Sandbox Code Playgroud)

然后形状a已经确定.因此numpy可以直接分配对象.

然而,在某种程度上,这是正确的,因为它a是一个向量.如果已使用不同的形状定义,则仍将进行方法访问.例如,下面仍然会调用___getitem__一个类

a = numpy.empty((1, 10), dtype=object)
a[0] = X()
print a
Run Code Online (Sandbox Code Playgroud)

回报

[[ x xx xxx xxxx xxxxx xxxxxx xxxxxxx xxxxxxxx xxxxxxxxx]]
Run Code Online (Sandbox Code Playgroud)