Нашли ошибку?
продвинутыйNumPy 2.5.3

Операции на месте и out=

Изменить массив без создания нового — экономия памяти на больших данных и частый источник неожиданных побочных эффектов.

Нужно знать:Представления и копииУниверсальные функции (ufunc)

Содержание статьи

Коротко

  • a += b, a *= 2 и другие составные операторы меняют массив на месте: новый массив не создаётся.
  • a = a + b создаёт новый массив и переназначает имя; другие ссылки на старый массив его не видят.
  • У любой ufunc есть out= — куда записать результат. np.sqrt(a, out=a) — корень на месте.
  • where= вместе с out= меняет только элементы, где условие истинно.
  • Тип массива при операции на месте не меняется: int += float — ошибка.

Синтаксис

a += b                        # на месте, тип a сохраняется
a = a + b                     # новый массив
np.multiply(a, 2, out=a)      # на месте через out
np.add(a, b, out=result)      # в заранее созданный массив
np.sqrt(a, out=a, where=a > 0)

Параметры

ПараметрЧто делаетПо умолчанию
outмассив для результата; форма должна совпадать с формой результатаNone
whereмаска: где False — out не меняетсяTrue
castingкакие преобразования типа разрешены при записи в out'same_kind'

Примеры

Данные для примеровиспользуются во всех примерах ниже
prices = np.array([100.0, 250.0, 80.0])
Новый массив и изменение на месте
alias = prices                 # вторая ссылка на тот же массив
prices = prices * 1.1          # новый массив; alias по-прежнему старый
print(alias)
alias *= 1.1                   # на месте: меняется сам массив
alias
Вывод
[100. 250.  80.]
array([110., 275.,  88.])
Результат в готовый массив
result = np.empty(3)
np.multiply(prices, 0.9, out=result)   # результат записан в готовый массив
result
Вывод
array([ 90., 225.,  72.])
ufunc на месте
np.sqrt(prices, out=prices)            # на месте для любой ufunc
prices.round(4)
Вывод
array([10.    , 15.8114,  8.9443])
На месте только часть элементов
values = np.array([4.0, -9.0, 16.0])
np.sqrt(values, out=values, where=values > 0)   # отрицательные остались как есть
values
Вывод
array([ 2., -9.,  4.])

Подводные камни

Целый массив и дробный результат

При += результат записывается в исходный массив его же типа, и NumPy отказывается молча отбрасывать дробную часть.

+= 0.5 для int-массиваошибка: UFuncTypeError
counts = np.array([1, 2, 3])
counts += 0.5                  # результат float не помещается в int-массив
Ошибка
UFuncTypeError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
Обычное присваивание
counts = np.array([1, 2, 3])
counts = counts + 0.5          # обычное присваивание создаёт float-массив
counts
Вывод
array([1.5, 2.5, 3.5])

Побочные эффекты через представления

Операция на месте над срезом или над массивом, переданным в функцию, меняет исходные данные — см. представления и копии.