2013-04-09 14 views
6
def f(x): 
    x=x/5. 
    return x 
def g(x): 
    x/=5. 
    return x 

x_var = np.arange(5,dtype=np.double) 
f(x_var) 
print x_var 
g(x_var) 
print x_var 

Output: 
[ 0. 1. 2. 3. 4.] 
[ 0. 0.2 0.4 0.6 0.8] 

Questo comportamento è un po 'strano per me, ho sempre pensato x/= 5. era equivalente a x = x/5. . Ma chiaramente la funzione g (x) non crea un nuovo riferimento con/= operazione. Qualcuno potrebbe offrire una spiegazione per questo?Comportamento imprevisto per numpy self division

risposta

5

Ho sempre pensato x/= 5. era equivalente a x = x/5

E ', a meno che la classe sostituisce l'operatore __idiv__, come numpy.ndarray fa. numpy.ndarray esegue l'override per modificare l'array sul posto, il che è buono perché evita di creare una nuova copia dell'array, quando la copia non è richiesta. Come puoi immaginare, prevale anche sul resto degli operatori __i*__.

+0

Grazie per la spiegazione, non sono riuscito a trovare la documentazione che mi avrebbe portato a prevedere questo comportamento. – bluecat

+5

Questo non è un problema di numpy, è un oggetto che passa per problema di riferimento. L'implementazione predefinita di tutti '__i * __' è di eseguire l'operazione sul posto se possibile, leggere i [documenti] (http://docs.python.org/reference/datamodel.html#object.__iadd__). Avrai lo stesso problema passando una lista Python ad una funzione che ha fatto "def f (a): a * = 3; return a', modificherebbe l'oggetto originale con il quale l'hai chiamato, non semplicemente restituirà una copia modificata. – Jaime

+1

Grazie, questo era il riferimento alla documentazione che stavo cercando. Quindi dovrebbe eseguire l'operazione sul posto, se possibile. Se __i * __ non è disponibile, per impostazione predefinita verrà eseguita l'operazione __ * __ normale. – bluecat

3

Gli operatori sul posto di Python consentono all'operazione di di modificare l'oggetto sul lato sinistro dell'equazione anziché crearne uno nuovo. Vedrete lo stesso comportamento con list s e altri tipi mutabili built-in:

x = [] 
y = x 
x += [1] 
print y # prints [1] because x still refers to the same object as y 
x = x + [2] 
print x # prints [1, 2] for obvious reasons 
print y # prints [1] again because x has been rebound to a new list 
      # while y still refers to the original one 

comportamento Quindi questo è previsto.

Quando si tratta di tipi immutabili, ovviamente, viene creato un nuovo oggetto, poiché quello esistente non può essere modificato.

0

Ho sempre pensato x/= 5. era equivalente a x = x/5.

Non lo è. Quando si esegue x=x/5., sei in realtà l'esecuzione di due operazioni separate sotto il cofano:

temporary = x/5. 
x = temporary 

mentre quando si utilizza l'operatore /=, si sta chiedendo esplicitamente Python di modificare l'oggetto x in atto , senza la creazione di un oggetto temporaneo. Come menzionato in altre risposte, l'operatore / chiama il metodo __div__ dell'oggetto (se presente), mentre lo /= chiama il metodo __idiv__.

La modifica sul posto è molto utile se l'oggetto che si sta modificando è di grandi dimensioni: non è necessario creare un oggetto temporaneo di dimensioni elevate. Tuttavia, può morderti se non stai attento. In particolare, di solito non è una grande idea che una funzione modifichi i suoi parametri di input senza preavviso ...

Problemi correlati