Poiché la stringa è immutabile (come una tupla), viene memorizzata con l'oggetto bytecode per la funzione. È caricato da una ricerca indice molto semplice e veloce. Questo è in realtà più veloce di una ricerca globale.
Si può vedere questo in un disassemblaggio del bytecode, utilizzando il dis.dis()
function:
>>> import dis
>>> def foo(s):
... c_string = "hello"
... if s == c_string:
... return True
... return False
...
>>> dis.dis(foo)
2 0 LOAD_CONST 1 ('hello')
3 STORE_FAST 1 (c_string)
3 6 LOAD_FAST 0 (s)
9 LOAD_FAST 1 (c_string)
12 COMPARE_OP 2 (==)
15 POP_JUMP_IF_FALSE 22
4 18 LOAD_GLOBAL 0 (True)
21 RETURN_VALUE
5 >> 22 LOAD_GLOBAL 1 (False)
25 RETURN_VALUE
>>> foo.__code__.co_consts
(None, 'hello')
Il LOAD_CONST
opcode carica l'oggetto stringa dalla matrice co_costs
che fa parte dell'oggetto codice per la funzione; il riferimento è spinto in cima allo stack. L'opcode STORE_FAST
prende il riferimento dalla cima dello stack e lo memorizza nell'array locale, di nuovo un'operazione molto semplice e veloce.
Per letterali mutabili ({..}
, [..]
) opcode speciali costruire l'oggetto, con il contenuto ancora trattati come costanti il più possibile (strutture più complesse basta seguire le stesse particelle elementari):
>>> def bar(): return ['spam', 'eggs']
...
>>> dis.dis(bar)
1 0 LOAD_CONST 1 ('spam')
3 LOAD_CONST 2 ('eggs')
6 BUILD_LIST 2
9 RETURN_VALUE
Il BUILD_LIST
call crea il nuovo oggetto lista, usando due oggetti stringa costanti.
Fatto interessante: se si utilizza un oggetto elenco per un test di appartenenza (something in ['option1', 'option2', 'option3']
Python sa che l'oggetto elenco non sarà mai mutato e lo convertirà in una tupla per te in fase di compilazione (una cosiddetta ottimizzazione spioncino). stesso vale per una serie letterale, che viene convertito in un oggetto frozenset()
, ma solo in Python 3.2 e successivi Vedi Tuple or list when using 'in' in an 'if' clause?
Nota che la funzione di esempio sta usando booleani piuttosto verboso, si potrebbe semplicemente aver usato:.
def foo(s):
c_string = "hello"
return s == c_string
per lo stesso risultato esatto, evitando lo LOAD_GLOBAL
chiamate in Python 2 (Python 3 ha creato True
e False
parole chiave in modo che i valori possano anche essere memorizzati come costanti).
Non succede la stessa cosa con 's ==" ciao "'? – jonrsharpe
Hai ragione riguardo al commento sulle tuple, avrei dovuto chiederti invece dell'elenco. Ill correggere la domanda. Il resto della risposta è eccellente per ora :) –
@ArthurVaiselbuh: Ho anche elencato gli elenchi ora, oltre a dizionari e set di '{...}'. –