2015-12-03 4 views
5

Dove è la differenza quando scrivo qualcosa su una riga, separato da uno , e su due righe. Apparentemente non capisco la differenza, perché anche se le due funzioni seguenti dovrebbero tornare uguali.Differenza tra scrivere qualcosa su una riga e su più righe

def fibi(n): 
    a, b = 0, 1 
    for i in range(n): 
     a, b = b, a + b 
    return a 

print(fibi(6)) 
> 8 # expected result (Fibonacci) 

Ma

def fibi(n): 
    a, b = 0, 1 
    for i in range(n): 
     a = b 
     b = a + b 
    return a 


print(fibi(6)) 
> 32 
+1

'a = b; b = a + b' è equivalente a 'a = b; b = b + b'. – bereal

risposta

13

Questo a causa della disimballaggio tupla di Python. Nella prima, Python raccoglie i valori a destra, li rende una tupla, quindi assegna i valori della tupla singolarmente ai nomi sulla sinistra. Quindi, se a == 1 e B == 2:

a, b = b, a + b 
=> a, b = (2, 3) 
=> a = 2, b = 3 

Ma nel secondo esempio, è normale assegnazione:

a = b 
=> a = 2 
    b = a + b 
=> b = 4 
+0

Oh wow. Non sapevo che Python lo facesse. Buona espanzione Grazie! – Stophface

1

tuo differenza è disponibile in sulle linee:

1)

>>> a, b = 0, 1 
>>> a, b = b, a+b 
>>> a 
1 
>>> b 
1 

vs:

2)

>>> a, b = 0, 1 
>>> a = b 
>>> b = a+b 
>>> a 
1 
>>> b 
2 

nel primo caso, e a = 1b = 0 + 1 prima che i valori della variabile sono cambiate. In pratica stai dicendo "con lo (a,b) allo stato X, imposta (a,b) su valori (0,1)".

Un buon modo per vedere la differenza in questo genere di cose è quello di utilizzare il modulo disassembly (clicca per vedere significato dei codici):

>>> from dis import dis 
>>> a, b = 0, 1 
>>> dis('a, b = b, a+b') 
    1   0 LOAD_NAME    0 (b) 
       3 LOAD_NAME    1 (a) 
       6 LOAD_NAME    0 (b) 
       9 BINARY_ADD 
      10 ROT_TWO 
      11 STORE_NAME    1 (a) 
      14 STORE_NAME    0 (b) 
      17 LOAD_CONST    0 (None) 
      20 RETURN_VALUE 
>>> a, b = 0, 1 
>>> dis('a = b; b = a+b') 
    1   0 LOAD_NAME    0 (b) 
       3 STORE_NAME    1 (a) 
       6 LOAD_NAME    1 (a) 
       9 LOAD_NAME    0 (b) 
      12 BINARY_ADD 
      13 STORE_NAME    0 (b) 
      16 LOAD_CONST    0 (None) 
      19 RETURN_VALUE 
0

La differenza è che nel secondo esempio si imposta a a b prima di fare riferimento a a. I tuoi valori sul secondo esempio saranno spenti. Ecco un esempio:

a = 5 
b = 6 

Es.1:

a, b = b, a+b // a = 6 and b = 11 

Es.2:

a = b // a = 6 
b = a + b // b = 6+6 or 12 

Il primo esempio è corretta

2

di trovare un sostituto per

a, b = b, a + b 

è necessario prendere coscienza che questa assegnazione viene eseguita "passo dopo passo".

Così il suo equivalente è

old_a = a 
a = b 
b = old_a + b # note the old_a here, as a has been replaced in the meanwhile. 

Demo:

def fibi(n): 
    a, b = 0, 1 
    for i in range(n): 
     a, b = b, a + b 
    return a 

def fibi2(n): 
    a, b = 0, 1 
    for i in range(n): 
    old_a = a 
    a = b 
    b = old_a + b 
    return a 

>>> fibi(0) 
0 
>>> fibi(1) 
1 
>>> fibi(2) 
1 
>>> fibi(3) 
2 
>>> fibi(4) 
3 
>>> fibi(5) 
5 
>>> fibi(6) 
8 
>>> fibi(7) 
13 
>>> 
>>> 
>>> 
>>> fibi2(0) 
0 
>>> fibi2(1) 
1 
>>> fibi2(2) 
1 
>>> fibi2(3) 
2 
>>> fibi2(4) 
3 
>>> fibi2(5) 
5 
>>> fibi2(6) 
8 
>>> fibi2(7) 
+0

Nota: scrivendolo come hai scritto, restituisce 8 con 'fibi (5)' mentre dovrebbe restituire 5. – Stophface

+0

@Chrissl Se usato esattamente come sopra e sostituendo la riga sopra, funziona come un fascino ... – glglgl

+0

Scusa, I scritto male qualcosa ... – Stophface

0

Al primo caso, i comandi

a, b = b, a + b; 

farà prima la somma a + b e poi farà l'assegnazione . In tal caso, b contiene sempre 1. Questo spiega perché il risultato finale è 6, perché stai aggiungendo 1 sei volte.

Il secondo codice che hai postato è corretto.

0

Una spiegazione perfetta da Raymond Hettinger può essere trovato in questo video PyCon 2013 tra 33:13 e 38:17:

https://www.youtube.com/watch?v=OSGv2VnC0go

Citazione di sua presentazione:

  • don Non sottovalutare i vantaggi dell'aggiornamento delle variabili di stato allo stesso tempo
  • elimina un'intera classe di errori a causa di aggiornamenti fuori servizio