Как сделать «изменяемое» число в массиве (numpy)? - PullRequest
0 голосов
/ 20 сентября 2018

Я пытаюсь создать массив, который включает в себя одно и то же число несколько раз, но если я изменю его в любом месте, он должен измениться везде.Как со списками:

a = b = [1]
>>> a.append(1)
>>> print(b)
>>> [1, 1]

Итак, я хочу такой массив:

number = 10   
arr = numpy.zeros((10, 10))
arr[0][0] = number
arr[1][1] = number
arr[0][0] += 1
print(arr[1][1])

Здесь он должен вывести «11».Так есть ли способ иметь несколько ссылок на номер?Я знаю, что вы могли бы заменить все 10 на 11, но, во-первых, это будет слишком неэффективно, во-вторых, это может испортить ситуацию, поскольку другое число может совпадать и с 10.

Спасибо.

1 Ответ

0 голосов
/ 20 сентября 2018

Нольмерный массив numy во многих отношениях ведет себя как изменяемое число:

>>> import numpy as np                                                  
>>>                                                                                                                 
>>> a = 2.0            # ordinary immutable number
>>> am = np.array(2.0) # "mutable number"                                                                                          
>>>                                                                                                                 
>>> A = np.array([[a, a, am, a], [am, am, a, a]], dtype=object)
>>> A
array([[2.0, 2.0, array(2.), 2.0],                                                                                  
       [array(2.), array(2.), 2.0, 2.0]], dtype=object)

Это немного некрасиво, поэтому ниже я преобразую в число с плавающей точкой перед печатью:

>>> A.astype(float)                                                          
array([[2., 2., 2., 2.],                                                                                            
       [2., 2., 2., 2.]])

Эти двое не все равны, верхний левый является неизменным

>>> A[0, 0] += 1

Это влияет на назначение только непосредственно адресуемой ячейки:

>>> A.astype(float)
array([[3., 2., 2., 2.],
       [2., 2., 2., 2.]])
>>> a
2.0

Третий два является изменяемым

>>> A[0, 2] -= 1

Назначение для него затрагивает все ссылки:

>>> A.astype(float)
array([[3., 2., 1., 2.],
       [1., 1., 2., 2.]])
>>> am
array(1.)

Прямое назначение требует [()] синтаксис:

>>> A[0, 2][()] = 1.5
>>> am
array(1.5)

В противном случае ссылка будет разорвана:

>>> A[0, 2] = 1.8
>>> A.astype(float)
array([[3. , 2. , 1.8, 2. ],
       [1.5, 1.5, 2. , 2. ]])

Обновление:

В комментарии OP указывается следующее желаемое поведение:

Если изменяемое число am встречается k раз в A, то в A * 3изменяемое число должно быть умножено на 3**k, а не 3.

Мы можем получить это поведение, используя оператор inplace (*=) и некоторые хитрости;Если мы хотим сохранить оригинал A, мы должны сначала сделать копию:

Поскольку копирующее устройство numpy s нормализует наши 0D-массивы, для создания хорошей копии требуется еще несколько хитростей:

>>> import copy
>>>
>>> B = np.empty_like(A)
>>> B.ravel()[...] = copy.deepcopy((*A.ravel(),))

Теперь выполните умножение на месте для копии:

>>> import operator as op
>>> 
>>> C = np.frompyfunc(op.imul, 2, 1)(B, 3)
>>> 
>>> A
array([[2.0, 2.0, array(2.), 2.0],
       [array(2.), array(2.), 2.0, 2.0]], dtype=object)
>>> C
array([[6.0, 6.0, array(54.), 6.0],
       [array(54.), array(54.), 6.0, 6.0]], dtype=object)

Обратите внимание, что B будет содержать некоторые бесполезные гибридные данные в конце и их следует отбросить.

>>> B
array([[2.0, 2.0, array(54.), 2.0],
       [array(54.), array(54.), 2.0, 2.0]], dtype=object)
>>> del B

Последнее замечание: это более хитрое, чем нормальное программирование, поэтому, пожалуйста, расценивайте его как «можно сделать», а не как следует ».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...