Название может быть немного запутанным, поэтому я надеюсь, что смогу прояснить его с помощью примера. У меня есть небольшая вспомогательная функция, которая добавляет новые поля к уже существующим структурированным массивам:
import numpy as np
def add_field(a, *descr):
b = np.empty(a.shape, dtype=a.dtype.descr + [*descr])
for name in a.dtype.names:
b[name] = a[name]
return b
Учитывая структурированный массив, я могу просто использовать его для добавления новых полей:
a = np.array(
[(1, False), (2, False), (3, False), (4, True)],
dtype=[('id', 'i4'), ('used', '?')]
)
print(a)
b = add_field(a, ('new', 'O'))
print(b)
Затем я могу без проблем установить запись во вновь созданном поле в (пустой) список:
b[0]['new'] = []
Я также могу создать новый массив, представляющий собой только фрагмент исходного, и затем добавить новое поле для этого нового массива:
c = a[0]
print(c)
d = add_field(c, ('newer', 'O'))
print(d)
НО, если я сейчас попытаюсь установить новое поле в (пустой) список, оно не будет работать:
d['newer'] = []
ValueError: assignment to 0-d array
Почему который? Согласно add_field
, d
- это совершенно новый массив, который имеет те же поля и записи, что и b
. Интересно, что форма b[0]
равна ()
, а форма d
равна (1,)
(а также type(b)
равна np.void
, а type(d)
равна np.array
). Может быть, это как-то связано с этим? Также интересно то, что все это работает:
d['newer'] = 1.34
d['newer'] = False
d['newer'] = None
d['newer'] = add_field
d['newer'] = set()
d['newer'] = {}
d['newer'] = {'test': []}
Однако доступ к файлам за последние dict
с помощью клавиши 'test'
не дает:
>>> d['newer'] = {'test': []}
>>> d['newer']
>>> array({'test': []}, dtype=object)
>>> d['newer']['test']
>>> IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices
>>> d['newer'][0]
>>> IndexError: too many indices for array
Это очень запутанно .
РЕДАКТИРОВАТЬ
Хорошо, я просто попытался изменить функцию add_field
следующим образом:
def add_field(a, *descr):
shape = a.shape if len(a.shape) else (1,)
b = np.empty(shape, dtype=a.dtype.descr + [*descr])
for name in a.dtype.names:
b[name] = a[name]
return b
Но это не помогло :
>>> d = add_field(a[0], ('newer', 'O'))
>>> d
>>> array([(1, False, None)], dtype=[('id', '<i4'), ('used', '?'), ('test', 'O')])
>>> d.shape
>>> (1,)
>>> d['newer'] = []
>>> ValueError: cannot copy sequence with size 0 to array axis with dimension 1
Так что это не было, я думаю. Однако теперь это работает:
>>> d['newer'][0] = []
Но мне не нравится этот обходной путь. Я ожидаю, что он будет работать так же, как и для b[0]
.
РЕДАКТИРОВАТЬ 2
Если я немного изменю функцию add_field
, я могу принудительно заставить желаемое поведение, хотя мне это не нравится на 100%:
def add_field(a, *descr):
shape = a.shape if len(a.shape) else (1,)
b = np.empty(shape, dtype=a.dtype.descr + [*descr])
for name in a.dtype.names:
b[name] = a[name]
return b if len(a.shape) else b[0]
d = add_field(a[0], ('newer', 'O'))
d['newer'] = []