индексация Python не меняет массив NumPy - PullRequest
3 голосов
/ 16 октября 2019
import numpy as np
a = np.array([[0, 1, 2],
              [0, 1, 2],
              [1, 1, 2]])

a[[0, 1]] = 100  # Changed
print(a)
a[[0, 1]][0, 0] = 98  # Not Changed
print(a)
a[0:2][0, 0] = 99  # Changed
print(a)

вывод:

# first
[[100 100 100]
[100 100 100]
[  1   1   2]]

# second
[[100 100 100]
[100 100 100]
[  1   1   2]]

# third
[[ 99 100 100]
[100 100 100]
[  1   1   2]]

так почему второй способ не изменил массив, а первый и третий способы сработали? Я погуглил много ответов, но все еще не понимаю.

1 Ответ

5 голосов
/ 16 октября 2019

Это сложно.

По сути, вы делаете расширенную индексацию в случае 1 и 2 и базовую индексацию в случае 3. Документ NumPy о состоянии расширенной индексации:

Расширенная индексация всегда возвращает копию данных (в отличие от базового среза, который возвращает представление).

Таким образом, мы уже знаем разницу между случаями 2 и 3. Случай 2 в основномэквивалентно

b = a[[0, 1]]
b[0, 0] = 98

Поскольку расширенная индексация создает копию, b больше не связана с a и изменения не отражаются. В случае 3 у нас есть

b = a[0:2]
b[0, 0] = 99

, где b теперь представляет собой представление a (базовое индексирование), поэтому изменения в b отражают в a.

Так что же происходит в случае 1?

Существенное отличие состоит в том, что вы не можете разделить это на присваивание b = ... и последующую операцию setitem. Вместо этого вы делаете setitem непосредственно для результата индексации, который не создает копию (только getitem работает с копиями). Таким образом, мы получаем то же поведение, что и в случае 2.

Это иллюстрирует следующее:

Дело 1 эквивалентно

setitem(a, [0, 1], 100)  # operates directly on a

Дело 2 эквивалентно

setitem(
    getitem(a, [0, 1]),  # this is a copy
    [0, 0],
    98
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...