+ = поведение при добавлении массива numpy в скаляр в python - PullRequest
0 голосов
/ 20 апреля 2020

У меня есть скалярная переменная и я хочу добавить массив numpy. Я был немного неаккуратным и запрограммировал его следующим образом:

import numpy as np
x = 5
x += np.ones(5)
print(x)

Этот код действительно выдает [6. 6. 6. 6. 6.], но, оглядываясь назад, я не понимаю, почему. В конце концов, я подумал, что += не создает новое место для x в памяти, а просто добавляет значения в то же место в памяти. Но то, что я добавил (массив длиной 5), требует намного большего места в памяти. Так почему же это работает? Должно ли это работать? Это сохранить?

Ответы [ 2 ]

0 голосов
/ 20 апреля 2020

Для скаляра:

In [128]: x = 23.2                                                                                     
In [129]: id(x)                                                                                        
Out[129]: 140067097316640
In [130]: x += 12                                                                                      
In [131]: x                                                                                            
Out[131]: 35.2
In [132]: id(x)                                                                                        
Out[132]: 140067097315080

+ = присвоил переменной новый номер.

Для массива:

In [133]: x = np.ones(3)                                                                               
In [134]: x                                                                                            
Out[134]: array([1., 1., 1.])
In [135]: id(x)                                                                                        
Out[135]: 140067132298464
In [136]: x.__array_interface__['data']                                                                
Out[136]: (140067416761584, False)
In [137]: x += 12                                                                                      
In [138]: id(x)                                                                                        
Out[138]: 140067132298464
In [139]: x.__array_interface__['data']                                                                
Out[139]: (140067416761584, False)
In [140]: x                                                                                            
Out[140]: array([13., 13., 13.])

добавление изменяет значения, но не объект массива (id) или даже его буфер данных. Действие все на месте.

Для списка += может изменить элемент списка без изменения остальной части списка:

In [141]: x = [1,2,3]                                                                                  
In [142]: x[1] +=12                                                                                    
In [143]: x                                                                                            
Out[143]: [1, 14, 3]

То же самое для Python Скалярное обозначение i += 1 является сокращенным синтаксическим c, но не меняет вычисления (но было бы хорошо взглянуть на сгенерированный байт-код).

Однако, как указано в np.ufunc.at документы,

https://numpy.org/doc/stable/reference/generated/numpy.ufunc.at.html#numpy .ufun c .at

, действие массива += буферизовано. x+=12 на самом деле x[:] = x+12.

0 голосов
/ 20 апреля 2020

__iadd__() не реализовано для типа int, поэтому оно возвращается к x = x + np.ones(5)

Например, если x является экземпляром класса с iadd * 1008 Метод * (), x + = y эквивалентен x = x .__ iadd __ (y). В противном случае рассматриваются x .__ add __ (y) и y .__ radd __ (x), как и при оценке x + y.

документация

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