2015-05-10 10 views

risposta

128

Non si sta confrontando per l'uguaglianza. Tu sei assegnando.

Python consente di assegnare a più obiettivi:

foo, bar = 1, 2 

assegna i due valori rispettivamente foo e bar,. Tutto ciò che serve è una sequenza o iterabile sul lato destro e una lista o tupla di nomi sulla sinistra.

Quando si esegue:

[] = "" 

assegnato un vuota sequenza (stringhe vuote sono sequenze ancora) ad una lista vuota di nomi.

E 'essenzialmente la stessa cosa che fare:

[foo, bar, baz] = "abc" 

dove si finisce con foo = "a", bar = "b" e baz = "c", ma con un minor numero di caratteri.

Non è possibile, tuttavia, assegnare a una stringa, quindi "" sul lato sinistro di un compito non funziona mai ed è sempre un errore di sintassi.

Vedere la Assignment statements documentation:

Un'istruzione di assegnamento valuta la lista delle espressioni (ricordiamo che questo può essere una singola espressione o un elenco separato da virgole, quest'ultimo producendo una tupla) e assegna l'oggetto risultante singolo ciascuno degli elenchi di destinazione, da sinistra a destra.

e

Assegnazione di un oggetto in un elenco di destinazione, opzionalmente racchiuso tra parentesi o parentesi quadre, è ricorsivamente definito come segue.

Enfasi di priorità.

Che Python non genera un errore di sintassi per la lista vuota è in realtà un po 'un bug! La grammatica ufficialmente documentata non consente un elenco di destinazione vuoto e per lo () vuoto si verifica un errore. Vedi bug 23275; è considerato un bug innocuo:

Il punto di partenza è riconoscere che questo è in giro da molto tempo ed è innocuo.

vedere anche Why is it valid to assign to an empty list but not to an empty tuple?

34

Essa segue le Assignment statements section regole dalla documentazione,

assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression) 

Se il target list è un elenco separato da virgole di obiettivi: L'oggetto deve essere un iterabile con lo stesso numero di elementi come ci sono bersagli nella lista di destinazione, e gli oggetti sono assegnati, da sinistra a destra, ai bersagli corrispondenti.

L'oggetto deve essere una sequenza con lo stesso numero di elementi quanti sono i target nell'elenco di destinazione e gli elementi sono assegnati, da sinistra a destra, ai target corrispondenti.

Quindi, quando si dice

[] = "" 

"" è un iterabile (qualsiasi stringa Python valido è un iterabile) e viene imballati sugli elementi della lista.

Per esempio,

>>> [a, b, c] = "123" 
>>> a, b, c 
('1', '2', '3') 

Dal momento che si dispone di una stringa vuota, e un elenco vuoto, non c'è nulla di disfare. Quindi, nessun errore.

Ma, provate questo

>>> [] = "1" 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
ValueError: too many values to unpack (expected 0) 
>>> [a] = "" 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
ValueError: need more than 0 values to unpack 

Nel caso [] = "1", si stanno cercando di decomprimere la stringa "1" su una lista vuota di variabili. Quindi lamenta "troppi valori da decomprimere (atteso 0)".

Allo stesso modo, nel caso [a] = "", si dispone di una stringa vuota, quindi nulla da decomprimere veramente, ma lo si sta decomprimendo su una variabile, che è, ancora una volta, impossibile. Ecco perché si lamenta "bisogno di più di 0 valori per decomprimere".

Oltre a questo, come avete notato,

>>> [] =() 

tiri anche nessun errore, perché () è una tupla vuota.

>>>() 
() 
>>> type(()) 
<class 'tuple'> 

e quando è scompattato su una lista vuota, non c'è nulla da disfare. Quindi nessun errore.


Ma, quando si fa

>>> "" = [] 
    File "<input>", line 1 
SyntaxError: can't assign to literal 
>>> "" =() 
    File "<input>", line 1 
SyntaxError: can't assign to literal 

come il messaggio di errore dice, si sta tentando di assegnare a una stringa letterale. Che non è possibile Ecco perché stai ricevendo gli errori. E 'come dire

>>> 1 = "one" 
    File "<input>", line 1 
SyntaxError: can't assign to literal 

Internals

Internamente, l'operazione di assegnazione sarà tradotto in codice UNPACK_SEQUENCE op,

>>> dis(compile('[] = ""', "string", "exec")) 
    1   0 LOAD_CONST    0 ('') 
       3 UNPACK_SEQUENCE   0 
       6 LOAD_CONST    1 (None) 

Qui, dal momento che la stringa è vuota, UNPACK_SEQUENCE decomprime 0 volte. Ma quando si ha qualcosa di simile

>>> dis(compile('[a, b, c] = "123"', "string", "exec")) 
    1   0 LOAD_CONST    0 ('123') 
       3 UNPACK_SEQUENCE   3 
       6 STORE_NAME    0 (a) 
       9 STORE_NAME    1 (b) 
      12 STORE_NAME    2 (c) 
      15 LOAD_CONST    1 (None) 
      18 RETURN_VALUE 

la sequenza 123 viene decompresso in allo stack, da destra a sinistra. Quindi, la parte superiore della pila sarebbe 1 e la successiva sarebbe 2 e l'ultima sarebbe 3. Quindi assegna dalla cima dello stack alle variabili dall'espressione lato sinistro una per una.


BTW, in Python, questo è il modo in cui è possibile eseguire più assegnazioni nella stessa espressione. Ad esempio,

a, b, c, d, e, f = u, v, w, x, y, z 

questo funziona perché i valori destri vengono usati per costruire una tupla e quindi dovrà essere installata sui valori sinistra.

>>> dis(compile('a, b, c, d, e, f = u, v, w, x, y, z', "string", "exec")) 
    1   0 LOAD_NAME    0 (u) 
       3 LOAD_NAME    1 (v) 
       6 LOAD_NAME    2 (w) 
       9 LOAD_NAME    3 (x) 
      12 LOAD_NAME    4 (y) 
      15 LOAD_NAME    5 (z) 
      18 BUILD_TUPLE    6 
      21 UNPACK_SEQUENCE   6 
      24 STORE_NAME    6 (a) 
      27 STORE_NAME    7 (b) 
      30 STORE_NAME    8 (c) 
      33 STORE_NAME    9 (d) 
      36 STORE_NAME    10 (e) 
      39 STORE_NAME    11 (f) 
      42 LOAD_CONST    0 (None) 
      45 RETURN_VALUE 

ma il classico scambio tecnica a, b = b, a utilizza rotazione di elementi in cima alla pila. Se si hanno solo due o tre elementi, vengono trattati con le istruzioni speciali ROT_TWO e ROT_THREE invece di costruire la tupla e decomprimere.

>>> dis(compile('a, b = b, a', "string", "exec")) 
    1   0 LOAD_NAME    0 (b) 
       3 LOAD_NAME    1 (a) 
       6 ROT_TWO 
       7 STORE_NAME    1 (a) 
      10 STORE_NAME    0 (b) 
      13 LOAD_CONST    0 (None) 
      16 RETURN_VALUE 
+0

È anche possibile utilizzare 'dis ('[] = ""')' 'senza chiamare la compilazione()'. –

+0

Puoi descrivere cosa succede se stai scambiando più di tre variabili/elementi, usando il metodo nel tuo ultimo esempio? – hexafraction

+0

@hexafraction Costruirà una nuova tupla con tutti gli elementi sul lato destro e quindi li decomprimerà sopra le variabili sul lato sinistro. – thefourtheye

Problemi correlati