Массив объектных массивов - PullRequest
9 голосов
/ 06 октября 2011

Недавно я столкнулся с проблемами при создании массивов объектов Numpy с использованием, например,

a = np.array([c], dtype=np.object)

, где c является экземпляром некоторого сложного класса, а в некоторых случаях Numpy пытается получить доступ к некоторым методам этого класса.Однако выполнение:

a = np.empty((1,), dtype=np.object)
a[0] = c

решает проблему.Мне любопытно, в чем разница между этими двумя.Почему в первом случае 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')

Этораспечатывает getitem дважды.По сути, если в классе присутствует __len__, то это может привести к неожиданному поведению.

1 Ответ

11 голосов
/ 06 октября 2011

В первом случае a = np.array([c], dtype=np.object) numpy ничего не знает о форме предполагаемого массива.

Например, когда вы определяете

d = range(10)
a = np.array([d])

Затем вы ожидаете, что numpy определитформа, основанная на длине d.

Таким же образом, в вашем случае, numpy попытается определить, определен ли len(c) и, если это так, получить доступ к элементам c через * 1012.*.

Вы можете увидеть эффект, определив класс, такой как

class X(object):
    def __len__(self): return 10
    def __getitem__(self, i): return "x" * i

Тогда

print numpy.array([X()], dtype=object)

производит

[[ x xx xxx xxxx xxxxx xxxxxx xxxxxxx xxxxxxxx xxxxxxxxx]]

Для контраставо втором случае

a = np.empty((1,), dtype=np.object)
a[0] = c

Тогда форма a уже определена.Таким образом, numpy может просто назначить объект напрямую.

Однако в некоторой степени это верно только в том случае, если a является вектором.Если он был определен с другой формой, доступ к методу все равно будет происходить.Следующий пример, например, будет вызывать ___getitem__ для класса

a = numpy.empty((1, 10), dtype=object)
a[0] = X()
print a

, возвращает

[[ x xx xxx xxxx xxxxx xxxxxx xxxxxxx xxxxxxxx xxxxxxxxx]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...