2013-06-21 34 views
5

In questo caso, perché x += y produce un risultato diverso da x = x + y?Numpy, perché `x + = y` produce un risultato diverso da` x = x + y`?

import numpy as np 

x = np.repeat([1], 10) 
y = np.random.random(len(x)) 

x += y 
print x 
# Output: [1 1 1 1 1 1 1 1 1 1] 

x = x + y 
print x 
# Output: [ 1.50859536 1.31434732 1.15147365 1.76979431 1.64727364 
#   1.02372535 1.39335253 1.71878847 1.48823703 1.99458116] 
+0

In effetti un duplicato. Risposta breve: dipende dall'implementazione dei metodi "dunder" magici '__add__' e' __iadd__' –

+3

** Questo non è un duplicato **, questo è specifico per 'numpy' – jamylak

+0

@jamylak Oh - anzi, buona cattura, Grazie! –

risposta

9

Sebbene la domanda collegata spieghi il problema generale, esiste una spiegazione specifica per numpy in questo caso particolare. Fondamentalmente, quelle risposte dicono "dipende dal tipo di variabili coinvolte", e quello che sto dando di seguito è la spiegazione per i tipi di numpy.

Quando si esegue x + y, numpy utilizza un tipo di dati "minimo comune denominatore" per il risultato. Poiché x è int e y è float, ciò significa che restituisce un array float.

Ma quando si esegue x += y, si sta forzando a conformarsi al dtype di x, che è int. Questo tronca la parte decimale e rimanda tutti i valori x a 1. In questo modo numpy definisce gli operatori di assegnazione aumentata: forza il valore di ritorno ad essere dello stesso dtype del target di assegnazione.

È possibile ottenere il primo comportamento dal secondo esempio eseguendo x = (x + y).astype(int) (forzando esplicitamente il dtype su int). È possibile ottenere il secondo comportamento dal primo esempio lasciando x = np.repeat([1.0], 10) (utilizzando un float rende x avere float dtype, quindi ora è possibile aggiungere senza il troncamento).

2

Questo è dovuta alla differenza tra __add__ e __iadd__ metodi

Comunque di solito la differenza è visibile tra mutevole vs oggetti immutabili

>>> x = np.repeat([1], 10) 
>>> y = np.random.random(len(x)) 
>>> x += y 
>>> x 
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) 

contrasto con

>>> x = np.repeat([1.0], 10) 
>>> x += y 
>>> x 
array([ 1.05192255, 1.00844068, 1.27569982, 1.40997015, 1.17270114, 
     1.27335121, 1.70719855, 1.72778867, 1.64679031, 1.23241938]) 

così __iadd__ sta causando il ritorno all'aggiunta int quando x è int tipo

Questo ha senso se ci pensate - x non può cambiare magicamente il tipo di esso è elementi (dove sarebbe memorizzare quelli byte extra)

per __add__ non c'è nessun problema produttrici una nuova schiera di galleggianti invece di interi

Problemi correlati