J'ai une variable scalaire et je veux ajouter un tableau numpy. J'étais un peu bâclé et je l'ai programmé comme suit

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

Ce code produit en effet [6. 6. 6. 6. 6.], mais avec le recul je ne comprends pas pourquoi. Après tout, je pensais que += ne crée pas un nouvel emplacement pour x en mémoire, mais ajoute simplement des valeurs au même emplacement en mémoire. Mais ce que j'ai ajouté (un tableau de longueur 5) nécessite un emplacement beaucoup plus grand en mémoire. Alors pourquoi ça marche? Cela devrait-il fonctionner? Est-ce une sauvegarde?

0
Mark Bakker 20 avril 2020 à 13:31

2 réponses

Meilleure réponse

Pour un scalaire:

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

Le + = a attribué un nouveau numéro à la variable.

Pour un tableau:

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.])

L'ajout modifie les valeurs, mais pas l'objet tableau (id) ni même son tampon de données. L'action est en place.

Pour une liste, += peut changer un élément de la liste, sans changer le reste de la liste:

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

Donc, pour les scalaires Python, la notation i += 1 est un raccourci syntaxique, mais ne change pas le calcul (mais il serait bon de regarder le bytecode généré).

Cependant, comme indiqué dans la documentation np.ufunc.at,

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

, l'action array += est mise en mémoire tampon. Le x+=12 est en fait x[:] = x+12.

0
hpaulj 20 avril 2020 à 18:30

__iadd__() n'est pas implémenté pour le type int, il revient donc à x = x + np.ones(5)

Par exemple, si x est une instance d'une classe avec une méthode iadd (), x + = y équivaut à x = x .__ iadd __ (y). Sinon, x .__ add __ (y) et y .__ radd __ (x) sont considérés, comme pour l'évaluation de x + y.

Documentation

0
V. Ayrat 20 avril 2020 à 15:01